perm filename CLOOPS.MSG[COM,LSP]2 blob
sn#836436 filedate 1987-03-16 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00616 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00089 00002 ∂04-Sep-86 2153 Owners-CommonLoopsCore↑.pa@Xerox.COM Whoppers and run-super
C00111 00003 ∂04-Sep-86 2226 Owners-commonloopscore↑.pa@Xerox.COM Varia
C00117 00004 ∂05-Sep-86 1637 Bobrow.pa@Xerox.COM Re: Defmethod syntax proposal
C00122 00005 ∂05-Sep-86 1637 Owners-commonloopscore↑.pa@Xerox.COM Varia [what a useless subject!]
C00130 00006 ∂05-Sep-86 1637 Bobrow.pa@Xerox.COM Re: Message selection, continued
C00138 00007 ∂05-Sep-86 1638 Owners-commonloopscore↑.pa@Xerox.COM Re: Varia [what a useless subject!]
C00141 00008 ∂05-Sep-86 1836 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Defmethod syntax proposal
C00146 00009 ∂05-Sep-86 1836 Owners-commonloopscore↑.pa@Xerox.COM Terminology: instances
C00149 00010 ∂05-Sep-86 1902 Bobrow.pa@Xerox.COM [Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>:
C00172 00011 ∂05-Sep-86 1955 Owners-CommonLoopsCore↑.PA@Xerox.COM Methods Selected by Predications More General Than Classes
C00182 00012 ∂08-Sep-86 1458 RPG Re: Defmethod syntax proposal
C00186 00013 ∂08-Sep-86 1500 RPG Re: Defmethod syntax proposal
C00191 00014 ∂08-Sep-86 1500 RPG Class versus Type System
C00197 00015 ∂08-Sep-86 1529 RPG Re: Methods Selected by Predications More General Than Classes
C00202 00016 ∂08-Sep-86 1533 RPG Class versus Type System
C00207 00017 ∂08-Sep-86 1535 RPG Generic Functions Defined by Defmethod
C00213 00018 ∂08-Sep-86 1537 RPG Re: Defmethod syntax proposal
C00217 00019 ∂08-Sep-86 1654 RPG Re: Defmethod syntax proposal
C00220 00020 ∂08-Sep-86 1654 RPG Generic Functions Defined by Defmethod
C00223 00021 ∂08-Sep-86 1727 RPG Re: Defmethod syntax proposal
C00227 00022 ∂08-Sep-86 1728 RPG Class versus Type System
C00232 00023 ∂09-Sep-86 2035 RPG Re: Subtypep
C00234 00024 ∂09-Sep-86 2244 RPG Re: Summary of features we all agree on
C00264 00025 ∂09-Sep-86 2244 RPG lack of word from the west coast
C00266 00026 ∂09-Sep-86 2324 RPG Class-of Versus Type-of
C00269 00027 ∂09-Sep-86 2336 RPG Things on which we agree
C00274 00028 ∂10-Sep-86 0837 RPG Re: [Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>:
C00277 00029 ∂10-Sep-86 0837 RPG Re: Subtypep
C00279 00030 ∂10-Sep-86 1730 RPG Getting together to work
C00281 00031 ∂11-Sep-86 1057 RPG Things on which we agree
C00290 00032 ∂11-Sep-86 1100 RPG Re: Things on which we agree
C00295 00033 ∂11-Sep-86 1103 RPG Re: Things on which we agree
C00300 00034 ∂11-Sep-86 1532 RPG Whoppers and Ontology
C00305 00035 ∂11-Sep-86 1610 RPG Re: Things on which we agree
C00311 00036 ∂12-Sep-86 0805 RPG specifying metaclass etc.
C00313 00037 ∂12-Sep-86 0812 RPG Re: Defmethod syntax proposal
C00320 00038 ∂12-Sep-86 1106 RPG Defmethod Syntax
C00324 00039 ∂12-Sep-86 1108 RPG Re: Defmethod syntax proposal
C00328 00040 ∂12-Sep-86 1245 RPG Re: Defmethod syntax proposal
C00337 00041 ∂12-Sep-86 1248 RPG Whoppers and Phenomenology
C00346 00042 ∂12-Sep-86 1545 RPG ordering of defclasses
C00350 00043 ∂12-Sep-86 1657 RPG Re: Defmethod syntax proposal
C00357 00044 ∂12-Sep-86 1752 RPG ordering of defclasses
C00361 00045 ∂12-Sep-86 1756 RPG Getting together to work
C00366 00046 ∂13-Sep-86 2051 RPG Defmethod syntax
C00376 00047 ∂13-Sep-86 2100 RPG abbreviated form of WITH
C00380 00048 ∂13-Sep-86 2101 RPG Re: Defmethod syntax
C00382 00049 ∂14-Sep-86 1112 Gregor.pa@Xerox.COM Re: Getting together to work
C00384 00050 ∂14-Sep-86 1118 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: ordering of defclasses
C00387 00051 ∂14-Sep-86 1622 Gregor.pa@Xerox.COM Method Naming and Identity Proposal
C00389 00052 ∂14-Sep-86 1817 Gregor.pa@Xerox.COM default optional arguments to a generic function
C00395 00053 ∂14-Sep-86 1837 Owners-commonloopscore↑.pa@Xerox.COM Method Identification
C00397 00054 ∂15-Sep-86 1152 Owners-commonloopscore↑.pa@Xerox.COM Method Identification
C00400 00055 ∂15-Sep-86 1152 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Defmethod syntax
C00403 00056 ∂15-Sep-86 1152 Owners-CommonLoopsCore↑.PA@Xerox.COM Method Naming and Identity Proposal
C00408 00057 ∂15-Sep-86 1437 Owners-CommonLoopsCore↑.pa@Xerox.COM default optional arguments to a generic function
C00421 00058 ∂15-Sep-86 1436 Masinter.pa@Xerox.COM Re: Defmethod syntax
C00424 00059 ∂15-Sep-86 1436 Owners-commonloopscore↑.pa@Xerox.COM Goals of the Specification
C00427 00060 ∂15-Sep-86 1615 Owners-commonloopscore↑.pa@Xerox.COM Goals of the Specification
C00432 00061 ∂15-Sep-86 1743 Masinter.pa@Xerox.COM Re: Goals of the Specification
C00435 00062 ∂15-Sep-86 2005 Owners-CommonLoopsCore↑.PA@Xerox.COM Defmethod syntax
C00437 00063 ∂15-Sep-86 2101 Owners-CommonLoopsCore↑.pa@Xerox.COM default optional arguments to a generic function
C00448 00064 ∂16-Sep-86 0626 Owners-CommonLoopsCore↑.PA@Xerox.COM Proposed Goals (Statement for OOPSLA)
C00460 00065 /sub
C00472 00066 ∂16-Sep-86 0630 Owners-commonloopscore↑.pa@Xerox.COM Re: Goals of the Specification
C00476 00067 ∂16-Sep-86 1128 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: default optional arguments to a generic function
C00481 00068 ∂16-Sep-86 1413 Gregor.pa@Xerox.COM the kinds of method lookup people claim they want
C00487 00069 ∂16-Sep-86 1841 Owners-CommonLoopsCore↑.pa@Xerox.COM run-super
C00503 00070 ∂16-Sep-86 1841 Owners-CommonLoopsCore↑.PA@Xerox.COM What we should agree on before OOPSLA
C00508 00071 ∂17-Sep-86 0856 Bobrow.pa@Xerox.COM Re: run-super
C00514 00072 ∂17-Sep-86 1036 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: default optional arguments to a generic function
C00522 00073 ∂17-Sep-86 1037 Kahn.pa@Xerox.COM Re: run-super
C00525 00074 ∂17-Sep-86 1037 Kahn.pa@Xerox.COM DEFCLASS should replace DEFSTRUCT
C00529 00075 ∂17-Sep-86 1632 Gregor.pa@Xerox.COM Re: What we should agree on before OOPSLA
C00532 00076 ∂17-Sep-86 1636 Gregor.pa@Xerox.COM The name of WITH
C00533 00077 ∂17-Sep-86 1637 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: Getting together to work
C00536 00078 ∂17-Sep-86 1636 Bobrow.pa@Xerox.COM Proposed Goals (Statement for OOPSLA)
C00548 00079 ∂17-Sep-86 1636 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: default optional arguments to a generic function
C00565 00080 ∂17-Sep-86 1636 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: run-super, whoppers, wrappers
C00583 00081 ∂17-Sep-86 1636 Gregor.pa@Xerox.COM required-xxx options to defclass
C00586 00082 ∂17-Sep-86 2028 Owners-CommonLoopsCore↑.pa@Xerox.COM DEFCLASS should replace DEFSTRUCT
C00589 00083 ∂17-Sep-86 2029 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: run-super
C00594 00084 ∂17-Sep-86 2029 Masinter.pa@Xerox.COM Re: DEFCLASS should replace DEFSTRUCT
C00599 00085 ∂17-Sep-86 2031 Owners-CommonLoopsCore↑.pa@Xerox.COM Proposed Goals (Statement for OOPSLA)
C00603 00086 ∂17-Sep-86 2224 Owners-CommonLoopsCore↑.pa@Xerox.COM The name of WITH
C00605 00087 ∂17-Sep-86 2224 Owners-CommonLoopsCore↑.pa@Xerox.COM required-xxx options to defclass
C00608 00088 ∂18-Sep-86 0625 Owners-CommonLoopsCore↑.pa@Xerox.COM The name of WITH
C00611 00089 ∂18-Sep-86 0811 Owners-CommonLoopsCore↑.pa@Xerox.COM Proposed Goals (Statement for OOPSLA)
C00629 00090 ∂18-Sep-86 0900 Bobrow.pa@Xerox.COM Re: The name of WITH
C00635 00091 ∂18-Sep-86 0900 Bobrow.pa@Xerox.COM Re: DEFCLASS should replace DEFSTRUCT
C00638 00092 ∂18-Sep-86 1100 Owners-commonloopscore↑.pa@Xerox.COM DEFCLASS should replace DEFSTRUCT
C00641 00093 ∂18-Sep-86 1100 Owners-commonloopscore↑.pa@Xerox.COM Proposed Goals (Statement for OOPSLA)
C00645 00094 ∂18-Sep-86 1100 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: The name of WITH
C00650 00095 ∂18-Sep-86 1306 Owners-CommonLoopsCore↑.pa@Xerox.COM WITH-SLOTS
C00654 00096 ∂18-Sep-86 1306 Owners-CommonLoops.pa@Xerox.COM common loops for franz
C00656 00097 ∂18-Sep-86 1724 RPG Proposed Goals (Statement for OOPSLA)
C00660 00098 ∂18-Sep-86 1724 RPG DEFCLASS should replace DEFSTRUCT
C00663 00099 ∂18-Sep-86 2312 Masinter.pa@Xerox.COM Re: The name of WITH
C00665 00100 ∂18-Sep-86 2312 Owners-CommonLoops.pa@Xerox.COM FTP problems.
C00668 00101 ∂18-Sep-86 2312 Masinter.pa@Xerox.COM Re: DEFCLASS should replace DEFSTRUCT
C00672 00102 ∂18-Sep-86 2313 Owners-CommonLoops.pa@Xerox.COM Re: common loops for franz
C00674 00103 ∂18-Sep-86 2313 Masinter.pa@Xerox.COM Re: FTP problems.
C00675 00104 ∂18-Sep-86 2313 Bobrow.pa@Xerox.COM Re: Proposed Goals (Statement for OOPSLA)
C00677 00105 ∂19-Sep-86 0806 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Summary of features we all agree on
C00684 00106 ∂19-Sep-86 0944 Bobrow.pa@Xerox.COM Re: Summary of features we all agree on
C00687 00107 ∂19-Sep-86 1132 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Summary of features we all agree on
C00693 00108 ∂19-Sep-86 1132 Kahn.pa@Xerox.COM Short names like MAKE
C00696 00109 ∂20-Sep-86 1132 Owners-commonloopscore↑.pa@Xerox.COM Short Names
C00699 00110 ∂21-Sep-86 1230 masinter.PA@Xerox.COM mutable vs immutable generic functions
C00703 00111 ∂21-Sep-86 1355 Bobrow.pa@Xerox.COM Syntax of DEFCLASS
C00706 00112 ∂21-Sep-86 1433 Owners-CommonLoopsCore↑.PA@Xerox.COM mutable vs immutable generic functions
C00715 00113 ∂21-Sep-86 1529 Owners-CommonLoopsCore↑.pa@Xerox.COM Syntax of DEFCLASS
C00725 00114 ∂21-Sep-86 1537 MASINTER.PA@Xerox.COM (change-class x y) => (setf (class-of x) y)?
C00727 00115 ∂21-Sep-86 1540 Bobrow.pa@Xerox.COM Generic Function Objects
C00731 00116 ∂21-Sep-86 1553 MASINTER.PA@Xerox.COM make vs make-instance
C00733 00117 ∂21-Sep-86 1615 Bobrow.pa@Xerox.COM Re: (change-class x y) => (setf (class-of x) y)?
C00735 00118 ∂21-Sep-86 1638 Kahn.pa@Xerox.COM Re: Short Names
C00737 00119 ∂21-Sep-86 1717 Kahn.pa@Xerox.COM Re: (change-class x y) => (setf (class-of x) y)?
C00740 00120 ∂21-Sep-86 1725 Kahn.pa@Xerox.COM Re: default optional arguments to a generic function
C00744 00121 ∂21-Sep-86 1812 Bobrow.pa@Xerox.COM default optional arguments to a generic function
C00752 00122 ∂21-Sep-86 1925 Bobrow.pa@Xerox.COM Class Precedence List
C00755 00123 ∂21-Sep-86 2233 MASINTER.PA@Xerox.COM initial class lattice
C00759 00124 ∂22-Sep-86 0123 MASINTER.PA@Xerox.COM another name for "run-super"
C00760 00125 ∂22-Sep-86 0829 Owners-commonloopscore↑.PA@Xerox.COM another name for "run-super"
C00763 00126 ∂22-Sep-86 0916 Owners-commonloopscore↑.PA@Xerox.COM initial class lattice
C00777 00127 ∂22-Sep-86 1024 Owners-CommonLoopsCore↑.pa@Xerox.COM Class Precedence List
C00785 00128 ∂22-Sep-86 1025 Bobrow.pa@Xerox.COM Re: Class Precedence List
C00789 00129 ∂22-Sep-86 1130 Owners-CommonLoopsCore↑.pa@Xerox.COM Generic Function Objects
C00795 00130 ∂22-Sep-86 1132 Gregor.pa@Xerox.COM Re: Class Precedence List
C00797 00131 ∂22-Sep-86 1300 Gregor.pa@Xerox.COM Re: Generic Function Objects
C00799 00132 ∂22-Sep-86 1410 masinter.pa@Xerox.COM Re: initial class lattice
C00804 00133 ∂22-Sep-86 1410 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: Class Precedence List
C00808 00134 ∂22-Sep-86 1510 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: Generic Function Objects
C00812 00135 ∂22-Sep-86 1511 masinter.pa@Xerox.COM Re: Syntax of DEFCLASS
C00819 00136 ∂22-Sep-86 1628 Owners-commonloopscore↑.PA@Xerox.COM Re: initial class lattice
C00823 00137 ∂22-Sep-86 1757 Owners-CommonLoopsCore↑.pa@Xerox.COM default optional arguments to a generic function
C00834 00138 ∂22-Sep-86 1814 masinter.pa@Xerox.COM Re: default optional arguments to a generic function
C00839 00139 ∂22-Sep-86 2229 MASINTER.pa@Xerox.COM class-of compiled objects
C00841 00140 ∂22-Sep-86 2236 MASINTER.pa@Xerox.COM generic function objects
C00843 00141 ∂23-Sep-86 0859 Owners-commonloopscore↑.pa@Xerox.COM class-of compiled objects
C00846 00142 ∂23-Sep-86 0902 Owners-CommonLoopsCore↑.PA@Xerox.COM Name of RUN-SUPER
C00849 00143 ∂23-Sep-86 1354 Owners-commonloopscore↑.PA@Xerox.COM Re: initial class lattice
C00853 00144 ∂24-Sep-86 2021 Owners-commonloopscore↑.PA@Xerox.COM Re: (change-class x y) => (setf (class-of x) y)?
C00857 00145 ∂24-Sep-86 2037 Owners-commonloopscore↑.PA@Xerox.COM Re: (change-class x y) => (setf (class-of x) y)?
C00859 00146 ∂25-Sep-86 0809 Bobrow.pa@Xerox.COM Re: Class Precedence List
C00861 00147 ∂25-Sep-86 0810 Bobrow.pa@Xerox.COM [Guy Steele <gls@Think.COM>: Syntax of defstruct versus
C00865 00148 ∂25-Sep-86 1229 masinter.pa@Xerox.COM Re: (change-class x y) => (setf (class-of x) y)?
C00868 00149 ∂25-Sep-86 1229 masinter.pa@Xerox.COM Re: initial class lattice
C00872 00150 ∂25-Sep-86 1358 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: Class Precedence List
C00876 00151 ∂26-Sep-86 0954 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: Class Precedence List
C00879 00152 ∂26-Sep-86 1330 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: Class Precedence List
C00885 00153 ∂26-Sep-86 1635 Gregor.pa@Xerox.COM missing excl-low file
C00887 00154 ∂29-Sep-86 1328 Owners-commonloops.pa@Xerox.COM getting connected
C00888 00155 ∂29-Sep-86 1816 Hostrop.PA@Xerox.COM {eris}<Lispcore>...
C00890 00156 ∂30-Sep-86 1701 Owners-CommonLoops.PA@Xerox.COM Anybody know how objects are represented in PCL?
C00892 00157 ∂06-Oct-86 1525 Bobrow.pa@Xerox.COM Taking the politics out of Standardization
C00895 00158 ∂06-Oct-86 1658 Owners-CommonLoopsCore↑.pa@Xerox.COM Taking the politics out of Standardization
C00898 00159 ∂06-Oct-86 2038 Owners-CommonLoops.PA@Xerox.COM Change of Address
C00900 00160 ∂06-Oct-86 2144 Owners-CommonLoopsCore↑.PA@Xerox.COM Method Combinations
C00902 00161 ∂07-Oct-86 0245 Owners-CommonLoops.PA@Xerox.COM missing excl-low file
C00904 00162 ∂07-Oct-86 0245 Owners-CommonLoops.PA@Xerox.COM Anybody know how objects are represented in PCL?
C00907 00163 ∂07-Oct-86 0244 Owners-commonloops.pa@Xerox.COM getting connected
C00909 00164 ∂07-Oct-86 1626 Gregor.pa@Xerox.COM Re: Anybody know how objects are represented in PCL?
C00912 00165 ∂07-Oct-86 1920 Owners-CommonLoopsCore↑.PA@Xerox.COM Computing the class precedence list
C00924 00166 ∂08-Oct-86 1514 Bobrow.pa@Xerox.COM Re: Method Combinations
C00926 00167 ∂08-Oct-86 1559 Bobrow.pa@Xerox.COM Summary of Object Standard Discussions
C00947 00168 ∂08-Oct-86 1817 Owners-commonloopscore↑.pa@Xerox.COM new files on CLS,LSP on SAIL
C00951 00169 ∂09-Oct-86 1505 Owners-CommonLoopsCore↑.pa@Xerox.COM Summary of Object Standard Discussions
C00966 00170 ∂09-Oct-86 1544 Owners-commonloopscore↑.pa@Xerox.COM Summary of Object Standard Discussions
C00971 00171 ∂09-Oct-86 1615 Owners-commonloopscore↑.pa@Xerox.COM "Classes" Document and Agreements Summary
C00984 00172 ∂09-Oct-86 1637 RPG Summary of Object Standard Discussions
C00999 00173 ∂09-Oct-86 1709 Bobrow.pa@Xerox.COM Re: Summary of Object Standard Discussions
C01009 00174 ∂09-Oct-86 1811 Owners-CommonLoopsCore↑.PA@Xerox.COM "Classes" Document and Agreements Summary
C01022 00175 ∂10-Oct-86 1601 Owners-CommonLoopsCore↑.pa@Xerox.COM Classes document available on SAIL
C01025 00176 ∂10-Oct-86 1601 Bobrow.pa@Xerox.COM Computing the class precedence list
C01028 00177 ∂10-Oct-86 1601 Gregor.pa@Xerox.COM yaccpla (yet another compute class precedence list algorithm)
C01034 00178 ∂13-Oct-86 1823 RPG Greetings
C01035 00179 ∂13-Oct-86 1832 Bobrow.pa@Xerox.COM Re: Summary of Object Standard Discussions (Repeat of last
C01045 00180 ∂13-Oct-86 2206 LGD new object system spec files
C01046 00181 ∂13-Oct-86 2333 Owners-CommonLoopsInternal↑.x@Xerox.COM Mailing list addition
C01048 00182 ∂14-Oct-86 0754 skeene@STONY-BROOK.SCRC.Symbolics.COM Re: Summary of Object Standard Discussions (Repeat of last
C01054 00183 ∂14-Oct-86 1659 RPG Anonymous Generic Function Proposal
C01059 00184 ∂14-Oct-86 1849 Gregor.pa@Xerox.COM Re: Anonymous Generic Function Proposal
C01062 00185 ∂15-Oct-86 0751 RPG Anonymous Generic Functions
C01064 00186 ∂15-Oct-86 1312 @MC.LCS.MIT.EDU:Moon@STONY-BROOK.SCRC.Symbolics.COM "Classes" Document and Agreements Summary
C01068 00187 ∂15-Oct-86 1503 Bobrow.pa@Xerox.COM Method Combination
C01077 00188 ∂15-Oct-86 1602 DLW@ALDERAAN.SCRC.Symbolics.COM Re: Anonymous Generic Function Proposal
C01079 00189 ∂15-Oct-86 1602 DLW@ALDERAAN.SCRC.Symbolics.COM Anonymous Generic Functions
C01083 00190 ∂15-Oct-86 1635 Masinter.pa@Xerox.COM Re: Anonymous Generic Functions
C01085 00191 ∂15-Oct-86 2018 kempf%hplabsc@hplabs.HP.COM Re: Anonymous Generic Functions
C01087 00192 ∂15-Oct-86 2136 Moon@STONY-BROOK.SCRC.Symbolics.COM Method combination -- writeup for revised syntax
C01115 00193 ∂16-Oct-86 1118 Moon@STONY-BROOK.SCRC.Symbolics.COM Anonymous Generic Function Proposal
C01118 00194 ∂16-Oct-86 1837 Gregor.pa@Xerox.COM Anonymous Generic Function Proposal
C01122 00195 ∂16-Oct-86 1922 Masinter.pa@Xerox.COM Re: Summary of Object Standard Discussions
C01124 00196 ∂16-Oct-86 2044 Moon@STONY-BROOK.SCRC.Symbolics.COM Anonymous Generic Function Proposal
C01127 00197 ∂16-Oct-86 2114 Moon@STONY-BROOK.SCRC.Symbolics.COM Method Combination
C01148 00198 ∂16-Oct-86 2220 Moon@STONY-BROOK.SCRC.Symbolics.COM Dispatching on optional/keyword arguments
C01157 00199 ∂17-Oct-86 0515 DLW@ALDERAAN.SCRC.Symbolics.COM Anonymous Generic Function Proposal
C01161 00200 ∂17-Oct-86 0948 masinter.PA@Xerox.COM Re: Dispatching on optional/keyword arguments
C01163 00201 ∂17-Oct-86 1037 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal
C01166 00202 ∂17-Oct-86 1037 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal
C01170 00203 ∂17-Oct-86 1237 kempf%hplabsc@hplabs.HP.COM Re: Method Combination
C01173 00204 ∂17-Oct-86 1430 RPG Re: Anonymous Generic Function Proposal
C01175 00205 ∂17-Oct-86 1652 Masinter.pa@Xerox.COM Re: Dispatching on optional/keyword arguments
C01177 00206 ∂17-Oct-86 1845 @MC.LCS.MIT.EDU:Moon@VALLECITO.SCRC.Symbolics.COM "Classes" Document and Agreements Summary
C01193 00207 ∂17-Oct-86 2146 Moon@STONY-BROOK.SCRC.Symbolics.COM Computing the class precedence list
C01200 00208 ∂17-Oct-86 2155 Moon@STONY-BROOK.SCRC.Symbolics.COM Clarification of declaration requested
C01202 00209 ∂17-Oct-86 2157 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Anonymous Generic Function Proposal
C01204 00210 ∂17-Oct-86 2159 Moon@STONY-BROOK.SCRC.Symbolics.COM Summary of Object Standard Discussions
C01210 00211 ∂17-Oct-86 2201 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Summary of Object Standard Discussions
C01215 00212 ∂19-Oct-86 1632 Masinter.pa@Xerox.COM Re: Summary of Object Standard Discussions
C01217 00213 ∂20-Oct-86 0805 Bobrow.pa@Xerox.COM Re: "Classes" Document and Agreements Summary
C01226 00214 ∂20-Oct-86 0921 Bobrow.pa@Xerox.COM Re: Computing the class precedence list
C01234 00215 ∂20-Oct-86 0928 Bobrow.pa@Xerox.COM Re: Summary of Object Standard Discussions
C01237 00216 ∂20-Oct-86 1345 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Dispatching on optional/keyword arguments
C01240 00217 ∂20-Oct-86 1408 Bobrow.pa@Xerox.COM Re: Summary of Object Standard Discussions
C01245 00218 ∂20-Oct-86 1455 RPG Remarks on Generic Functions
C01268 00219 ∂20-Oct-86 1522 RPG Re: Summary of Object Standard Discussions
C01273 00220 ∂20-Oct-86 1759 Bobrow.pa@Xerox.COM Re: Method combination -- writeup for revised syntax
C01284 00221 ∂20-Oct-86 1923 Moon@STONY-BROOK.SCRC.Symbolics.COM Instance transformation protocol proposal
C01293 00222 ∂21-Oct-86 0703 DLW@ALDERAAN.SCRC.Symbolics.COM Instance transformation protocol proposal
C01296 00223 ∂21-Oct-86 0711 RPG Re: Remarks on Generic Functions
C01301 00224 ∂21-Oct-86 0928 kempf%hplabsc@hplabs.HP.COM Re: Remarks on Generic Functions
C01308 00225 ∂21-Oct-86 1049 Gregor.pa@Xerox.COM Instance transformation protocol proposal
C01312 00226 ∂21-Oct-86 1111 DLW@ALDERAAN.SCRC.Symbolics.COM Remarks on Generic Functions
C01316 00227 ∂21-Oct-86 1130 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Computing the class precedence list
C01319 00228 ∂21-Oct-86 1220 RPG Re: Remarks on Generic Functions
C01321 00229 ∂21-Oct-86 1320 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Summary of Object Standard Discussions
C01324 00230 ∂21-Oct-86 1601 Bobrow.pa@Xerox.COM Re: Computing the class precedence list
C01326 00231 ∂21-Oct-86 1602 Bobrow.pa@Xerox.COM Re: Remarks on Generic Functions
C01333 00232 ∂21-Oct-86 1604 Gregor.pa@Xerox.COM Re: Summary of Object Standard Discussions
C01336 00233 ∂21-Oct-86 2302 DUSSUD%Jenner%ti-csl.csnet@CSNET-RELAY.ARPA Re: Summary of Object Standard Discussions
C01339 00234 ∂22-Oct-86 1407 RPG DEF-GENERIC-OPTIONS
C01346 00235 ∂22-Oct-86 1513 Bobrow.pa@Xerox.COM Re: DEF-GENERIC-OPTIONS
C01349 00236 ∂23-Oct-86 1835 Masinter.pa@Xerox.COM Re: Dispatching on optional/keyword arguments
C01353 00237 ∂23-Oct-86 1836 Masinter.pa@Xerox.COM :TYPE in DEFCLASS?
C01354 00238 ∂23-Oct-86 2337 RPG Re: DEF-GENERIC-OPTIONS
C01360 00239 ∂24-Oct-86 1321 Masinter.pa@Xerox.COM Re: Dispatching on optional/keyword arguments
C01362 00240 ∂26-Oct-86 2029 Kahn.pa@Xerox.COM Re: Instance transformation protocol proposal
C01364 00241 ∂26-Oct-86 2029 Kahn.pa@Xerox.COM Re: Remarks on Generic Functions
C01367 00242 ∂26-Oct-86 2029 Kahn.pa@Xerox.COM Re: Anonymous Generic Function Proposal
C01369 00243 ∂26-Oct-86 2029 Kahn.pa@Xerox.COM Re: DEF-GENERIC-OPTIONS
C01372 00244 ∂27-Oct-86 1216 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal
C01375 00245 ∂27-Oct-86 1415 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Instance transformation protocol proposal
C01378 00246 ∂27-Oct-86 1510 edsel!bhopal!jonl@navajo.stanford.edu Remarks on Generic Functions
C01388 00247 ∂27-Oct-86 1920 Moon@STONY-BROOK.SCRC.Symbolics.COM Remarks on Generic Functions
C01392 00248 ∂27-Oct-86 1936 LGD new files on [CLS,LSP]
C01393 00249 ∂27-Oct-86 2034 RPG Re: Remarks on Generic Functions
C01398 00250 ∂27-Oct-86 2151 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Remarks on Generic Functions
C01408 00251 ∂28-Oct-86 0631 edsel!bhopal!jonl@navajo.stanford.edu Remarks on Generic Functions
C01413 00252 ∂28-Oct-86 0631 edsel!bhopal!jonl@navajo.stanford.edu Lexical GFLABELS versus "dynamic" GFLABELS
C01417 00253 ∂28-Oct-86 0753 RPG GLFET
C01421 00254 ∂28-Oct-86 1112 Moon@STONY-BROOK.SCRC.Symbolics.COM Lexical GFLABELS versus "dynamic" GFLABELS
C01424 00255 ∂28-Oct-86 1459 Pavel.pa@xerox.com Re: Lexical GFLABELS versus "dynamic" GFLABELS
C01427 00256 ∂28-Oct-86 1931 Moon@STONY-BROOK.SCRC.Symbolics.COM new files on [CLS,LSP]
C01429 00257 ∂28-Oct-86 2004 LGD printing files
C01431 00258 ∂29-Oct-86 0214 DUSSUD@martha Re: Instance transformation pr
C01434 00259 ∂29-Oct-86 0510 edsel!bhopal!jonl@navajo.stanford.edu Lexical GFLABELS versus "dynamic" GFLABELS
C01439 00260 ∂29-Oct-86 0919 kempf%hplabsc@hplabs.HP.COM Re: printing files
C01441 00261 ∂29-Oct-86 1035 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Instance transformation pr
C01444 00262 ∂29-Oct-86 1615 kempf%hplabsc@hplabs.HP.COM Re: Local Lexical Generic Functions
C01446 00263 ∂29-Oct-86 1755 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Dispatching on optional/keyword arguments
C01449 00264 ∂30-Oct-86 1333 Moon@STONY-BROOK.SCRC.Symbolics.COM new files on [CLS,LSP]
C01455 00265 ∂30-Oct-86 1452 DUSSUD%Jenner%ti-csl.csnet@CSNET-RELAY.ARPA
C01458 00266 ∂30-Oct-86 1728 LGD stripped down versions of files
C01459 00267 ∂31-Oct-86 1603 DUSSUD%Jenner%ti-csl.csnet@CSNET-RELAY.ARPA A proposal for a finer grained method combination selection.
C01467 00268 ∂05-Nov-86 0850 hpfclp!robert@hplabs.HP.COM discussion wanted
C01475 00269 ∂05-Nov-86 1255 RPG Next Step
C01476 00270 ∂05-Nov-86 2129 Moon@STONY-BROOK.SCRC.Symbolics.COM Next Step
C01480 00271 ∂05-Nov-86 2235 Moon@STONY-BROOK.SCRC.Symbolics.COM stripped down versions of files
C01483 00272 ∂06-Nov-86 0700 Masinter.pa@Xerox.COM Re: discussion wanted
C01493 00273 ∂06-Nov-86 1227 Kahn.pa@Xerox.COM Re: discussion wanted
C01496 00274 ∂06-Nov-86 1700 masinter.PA@Xerox.COM Re: discussion wanted
C01498 00275 ∂08-Nov-86 1319 RPG Clarification
C01500 00276 ∂08-Nov-86 1442 kempf%hplabsc@hplabs.HP.COM Re: Clarification
C01502 00277 ∂09-Nov-86 1900 Moon@STONY-BROOK.SCRC.Symbolics.COM Clarification
C01507 00278 ∂10-Nov-86 1003 Gregor.pa@Xerox.COM Re: Clarification
C01511 00279 ∂10-Nov-86 1224 Bobrow.pa@Xerox.COM Re: Clarification
C01515 00280 ∂10-Nov-86 1301 Bobrow.pa@Xerox.COM Re: Clarification
C01517 00281 ∂10-Nov-86 1801 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Clarification
C01521 00282 ∂11-Nov-86 1132 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Draft Comments Part II
C01526 00283 ∂11-Nov-86 1311 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Method combination -- writeup for revised syntax
C01529 00284 ∂12-Nov-86 0811 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Draft Comments Part I
C01534 00285 ∂12-Nov-86 0820 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Draft Comments
C01537 00286 ∂12-Nov-86 1225 Moon@ALDERAAN.SCRC.Symbolics.COM Comments on the function chapter
C01549 00287 ∂12-Nov-86 1256 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Next Step
C01553 00288 ∂12-Nov-86 2241 @MC.LCS.MIT.EDU:MOON%ML.AI.MIT.EDU@MC.LCS.MIT.EDU Second installment of comments on Functions chapter
C01571 00289 ∂13-Nov-86 1217 RPG ARGUMENT-PRECEDENCE-ORDER
C01572 00290 ∂13-Nov-86 1438 Moon@STONY-BROOK.SCRC.Symbolics.COM ARGUMENT-PRECEDENCE-ORDER
C01575 00291 ∂13-Nov-86 1514 masinter.pa@Xerox.COM Re: ARGUMENT-PRECEDENCE-ORDER
C01577 00292 ∂14-Nov-86 0047 RPG Altering Generic Functions
C01582 00293 ∂14-Nov-86 0951 Gregor.pa@Xerox.COM Re: Altering Generic Functions
C01585 00294 ∂14-Nov-86 0951 Gregor.pa@Xerox.COM Re: Altering Generic Functions
C01587 00295 ∂14-Nov-86 0950 MASINTER.PA@Xerox.COM Re: Altering Generic Functions
C01589 00296 ∂14-Nov-86 1114 masinter.pa@Xerox.COM Re: Altering Generic Functions
C01592 00297 ∂14-Nov-86 1626 Bobrow.pa@Xerox.COM Re: Altering Generic Functions
C01595 00298 ∂14-Nov-86 1746 RPG Altering Things
C01599 00299 ∂14-Nov-86 1806 Gregor.pa@Xerox.COM Re: Second installment of comments on Functions chapter
C01605 00300 ∂14-Nov-86 1816 RPG Remarks on Moon's Comments
C01607 00301 ∂14-Nov-86 1906 Bobrow.pa@Xerox.COM Re: Altering Generic Functions
C01609 00302 ∂14-Nov-86 1906 Bobrow.pa@Xerox.COM Re: Altering Things
C01613 00303 ∂14-Nov-86 1906 Gregor.pa@Xerox.COM Meeting at X3J13
C01615 00304 ∂14-Nov-86 1906 Bobrow.pa@Xerox.COM Re: Remarks on Moon's Comments
C01617 00305 ∂14-Nov-86 2030 Bobrow.pa@Xerox.COM Re: Meeting at X3J13
C01619 00306 ∂14-Nov-86 2105 RPG Meeting at X3J13
C01620 00307 ∂15-Nov-86 1213 kempf%hplabsc@hplabs.HP.COM Re: Meeting at X3J13
C01622 00308 ∂15-Nov-86 1353 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: discussion wanted
C01627 00309 ∂16-Nov-86 1020 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Meeting at X3J13
C01629 00310 ∂17-Nov-86 1100 Bobrow.pa@Xerox.COM Re: Meeting at X3J13
C01631 00311 ∂17-Nov-86 1807 Bobrow.pa@Xerox.COM Options of defclass
C01634 00312 ∂17-Nov-86 1807 Gregor.pa@Xerox.COM change class protocol
C01641 00313 ∂17-Nov-86 1809 Gregor.pa@Xerox.COM portable interface to code walker
C01644 00314 ∂18-Nov-86 0738 kempf%hplabsc@hplabs.HP.COM Re: change class protocol
C01646 00315 ∂18-Nov-86 0804 kempf%hplabsc@hplabs.HP.COM Re: portable interface to code walker
C01651 00316 ∂18-Nov-86 1026 Gregor.pa@Xerox.COM Re: change class protocol
C01653 00317 ∂18-Nov-86 1026 kahn.pa@Xerox.COM Re: change class protocol
C01655 00318 ∂18-Nov-86 1710 kahn.pa@Xerox.COM Re: Second installment of comments on Functions chapter
C01658 00319 ∂21-Nov-86 2027 Moon@STONY-BROOK.SCRC.Symbolics.COM Options of defclass
C01664 00320 ∂21-Nov-86 2122 Moon@STONY-BROOK.SCRC.Symbolics.COM Class precedence list, underconstrained method ordering
C01674 00321 ∂22-Nov-86 1048 RPG Options of Defclass
C01676 00322 ∂24-Nov-86 1810 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Meeting at X3J13
C01678 00323 ∂25-Nov-86 1339 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: portable interface to code walker
C01681 00324 ∂25-Nov-86 1445 Gregor.pa@Xerox.COM :accessor-prefix questions
C01686 00325 ∂26-Nov-86 0819 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: portable interface to code walker
C01689 00326 ∂26-Nov-86 0857 Bobrow.pa@Xerox.COM Re: :accessor-prefix questions
C01692 00327 ∂26-Nov-86 0910 Bobrow.pa@Xerox.COM "Do it using the meta-object protocol"
C01694 00328 ∂26-Nov-86 0913 Bobrow.pa@Xerox.COM Re: Options of defclass
C01696 00329 ∂28-Nov-86 1609 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: portable interface to code walker
C01700 00330 ∂28-Nov-86 1619 Moon@STONY-BROOK.SCRC.Symbolics.COM :accessor-prefix questions
C01709 00331 ∂30-Nov-86 1238 Masinter.pa@Xerox.COM Re: :accessor-prefix questions
C01713 00332 ∂30-Nov-86 1402 Gregor.pa@Xerox.COM Re: :accessor-prefix questions
C01719 00333 ∂30-Nov-86 1737 Gregor.pa@Xerox.COM Re: portable interface to code walker
C01729 00334 ∂30-Nov-86 1759 Gregor.pa@Xerox.COM initialization protocol strawman
C01737 00335 ∂30-Nov-86 2126 LGD new functions.* files on SAIL
C01738 00336 ∂01-Dec-86 1100 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: :accessor-prefix questions
C01744 00337 ∂01-Dec-86 1136 edsel!bhopal!jonl@navajo.stanford.edu :accessor-prefix questions
C01749 00338 ∂01-Dec-86 1326 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: portable interface to code walker
C01752 00339 ∂01-Dec-86 1613 Gregor.pa@Xerox.COM Re: portable interface to code walker
C01756 00340 ∂01-Dec-86 1850 Bobrow.pa@Xerox.COM Re: Class precedence list, underconstrained method ordering
C01763 00341 ∂02-Dec-86 1316 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: portable interface to code walker
C01765 00342 ∂02-Dec-86 1338 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: portable interface to code walker
C01768 00343 ∂02-Dec-86 1631 Gregor.pa@Xerox.COM code for compute-class-precedence-list
C01779 00344 ∂02-Dec-86 1921 Bobrow.pa@Xerox.COM Re: :accessor-prefix questions
C01783 00345 ∂03-Dec-86 2126 Moon@STONY-BROOK.SCRC.Symbolics.COM Comments on the revised function chapter
C01814 00346 ∂05-Dec-86 1035 Gregor.pa@Xerox.COM &key &allow-other-keys
C01816 00347 ∂06-Dec-86 0732 masinter.pa@Xerox.COM Re: :accessor-prefix questions
C01820 00348 ∂09-Dec-86 1722 Gregor.pa@Xerox.COM Re: Comments on the revised function chapter
C01842 00349 ∂12-Dec-86 1450 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: :accessor-prefix questions
C01845 00350 ∂12-Dec-86 1911 Bobrow.pa@Xerox.COM Re: Comments on the revised function chapter
C01855 00351 ∂13-Dec-86 0915 skeene@STONY-BROOK.SCRC.Symbolics.COM restrictions on change-class
C01863 00352 ∂16-Dec-86 1206 RPG My remarks on Moon's comments etc.
C01867 00353 ∂16-Dec-86 1422 Moon@STONY-BROOK.SCRC.Symbolics.COM Gabriel's remarks on Moon's comments etc.
C01872 00354 ∂16-Dec-86 1453 RPG Argument Precedence Order
C01874 00355 ∂16-Dec-86 1509 RPG Onward ... Soldiers
C01876 00356 ∂16-Dec-86 1642 Moon@STONY-BROOK.SCRC.Symbolics.COM Onward ... Soldiers
C01878 00357 ∂16-Dec-86 1657 RPG Planning
C01880 00358 ∂17-Dec-86 0729 skeene@STONY-BROOK.SCRC.Symbolics.COM My remarks on Moon's comments etc.
C01884 00359 ∂17-Dec-86 1234 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Comments on the revised function chapter
C01886 00360 ∂17-Dec-86 1246 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Comments on the revised function chapter
C01888 00361 ∂17-Dec-86 1510 RPG Rephrasing
C01890 00362 ∂17-Dec-86 1524 Moon@RIVERSIDE.SCRC.Symbolics.COM Re: Comments on the revised function chapter
C01894 00363 ∂17-Dec-86 1533 Moon@RIVERSIDE.SCRC.Symbolics.COM Implementation-supplied methods for DESCRIBE and PRINT-OBJECT
C01897 00364 ∂17-Dec-86 1542 RPG Implementation-supplied etc
C01898 00365 ∂17-Dec-86 1631 Gregor.pa@Xerox.COM Re: Comments on the revised function chapter
C01904 00366 ∂17-Dec-86 1634 Moon@STONY-BROOK.SCRC.Symbolics.COM specializers list
C01910 00367 ∂17-Dec-86 1702 Gregor.pa@Xerox.COM Re: specializers list
C01914 00368 ∂17-Dec-86 2033 Moon@STONY-BROOK.SCRC.Symbolics.COM Uninitialized slots
C01918 00369 ∂17-Dec-86 2110 RPG Uninitialized Slots
C01922 00370 ∂17-Dec-86 2120 Moon@STONY-BROOK.SCRC.Symbolics.COM Relationship between accessors and methods
C01926 00371 ∂18-Dec-86 0846 skeene@STONY-BROOK.SCRC.Symbolics.COM Changes made to the document
C01951 00372 ∂18-Dec-86 0848 skeene@STONY-BROOK.SCRC.Symbolics.COM List of open issues
C01964 00373 ∂18-Dec-86 0849 skeene@STONY-BROOK.SCRC.Symbolics.COM formatting changes needed
C01968 00374 ∂18-Dec-86 1229 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Comments on the revised function chapter
C01977 00375 ∂18-Dec-86 1345 Gregor.pa@Xerox.COM Re: Implementation-supplied etc
C01979 00376 ∂19-Dec-86 2055 Moon@STONY-BROOK.SCRC.Symbolics.COM DECLARE option to DEFGENERIC(-OPTIONS)
C01987 00377 ∂19-Dec-86 2106 Moon@STONY-BROOK.SCRC.Symbolics.COM with-slots & interning of constructed symbols
C01991 00378 ∂20-Dec-86 1243 RPG DECLARE option to DEFGENERIC(-OPTIONS)
C01995 00379 ∂20-Dec-86 2333 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Comments on the revised function chapter
C01999 00380 ∂21-Dec-86 1657 masinter.PA@Xerox.COM with-slots
C02002 00381 ∂22-Dec-86 1211 Bobrow.pa@Xerox.COM Re: DECLARE option to DEFGENERIC(-OPTIONS)
C02006 00382 ∂22-Dec-86 1211 Bobrow.pa@Xerox.COM Re: with-slots & interning of constructed symbols
C02008 00383 ∂22-Dec-86 1218 Moon@STONY-BROOK.SCRC.Symbolics.COM DECLARE option to DEFGENERIC(-OPTIONS)
C02012 00384 ∂22-Dec-86 1310 RPG DECLARE option to DEFGENERIC(-OPTIONS)
C02014 00385 ∂22-Dec-86 1348 Bobrow.pa@Xerox.COM Re: DECLARE option to DEFGENERIC(-OPTIONS)
C02016 00386 ∂22-Dec-86 1358 Bobrow.pa@Xerox.COM Re: Comments on the revised function chapter
C02020 00387 ∂22-Dec-86 1745 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: with-slots & interning of constructed symbols
C02023 00388 ∂22-Dec-86 1931 Moon@STONY-BROOK.SCRC.Symbolics.COM DECLARE option to DEFGENERIC(-OPTIONS)
C02029 00389 ∂22-Dec-86 2259 masinter.pa@Xerox.COM Re: with-slots & interning of constructed symbols
C02032 00390 ∂23-Dec-86 0031 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Comments on the revised function chapter
C02036 00391 ∂23-Dec-86 1018 Bobrow.pa@Xerox.COM Re: with-slots & interning of constructed symbols
C02039 00392 ∂23-Dec-86 1310 skeene@STONY-BROOK.SCRC.Symbolics.COM documentation revised
C02043 00393 ∂23-Dec-86 1327 Gregor.pa@Xerox.COM Re: Uninitialized Slots
C02046 00394 ∂23-Dec-86 1429 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Relationship between accessors and methods
C02053 00395 ∂23-Dec-86 1451 Gregor.pa@Xerox.COM Re: DECLARE option to DEFGENERIC(-OPTIONS)
C02055 00396 ∂23-Dec-86 1457 Gregor.pa@Xerox.COM Re: Comments on the revised function chapter
C02059 00397 ∂23-Dec-86 1729 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Relationship between accessors and methods
C02063 00398 ∂24-Dec-86 1502 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Comments on the revised function chapter
C02068 00399 ∂24-Dec-86 1504 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: DECLARE option to DEFGENERIC(-OPTIONS)
C02071 00400 ∂24-Dec-86 1506 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Comments on the revised function chapter
C02076 00401 ∂24-Dec-86 1504 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: specializers list
C02081 00402 ∂28-Dec-86 1358 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: DECLARE option to DEFGENERIC(-OPTIONS)
C02085 00403 ∂28-Dec-86 1419 Moon@STONY-BROOK.SCRC.Symbolics.COM make-method issue
C02089 00404 ∂28-Dec-86 1426 Moon@STONY-BROOK.SCRC.Symbolics.COM :method-class option to DEFGENERIC-OPTIONS
C02092 00405 ∂28-Dec-86 1557 Moon@STONY-BROOK.SCRC.Symbolics.COM terminology confusion
C02104 00406 ∂28-Dec-86 1618 Moon@STONY-BROOK.SCRC.Symbolics.COM MAKE-METHOD arguments discussion
C02110 00407 ∂28-Dec-86 1656 RPG Question about MAKE-METHOD Arguments
C02112 00408 ∂28-Dec-86 1807 Moon@STONY-BROOK.SCRC.Symbolics.COM Question about MAKE-METHOD Arguments
C02116 00409 ∂28-Dec-86 2040 Moon@STONY-BROOK.SCRC.Symbolics.COM Note to go into the Concepts chapter
C02120 00410 ∂28-Dec-86 2112 Moon@STONY-BROOK.SCRC.Symbolics.COM :allocation slot-option issues
C02128 00411 ∂29-Dec-86 1129 RPG Terminology
C02129 00412 ∂29-Dec-86 1201 RPG Standard-type-class
C02131 00413 ∂29-Dec-86 1218 Moon@STONY-BROOK.SCRC.Symbolics.COM Issues in Concepts chapter
C02135 00414 ∂29-Dec-86 1302 Moon@STONY-BROOK.SCRC.Symbolics.COM Standard-type-class
C02140 00415 ∂29-Dec-86 1333 RPG STANDARD-TYPE-CLASS
C02142 00416 ∂29-Dec-86 1829 Bobrow.pa@Xerox.COM Re: :method-class option to DEFGENERIC-OPTIONS
C02146 00417 ∂29-Dec-86 1829 Bobrow.pa@Xerox.COM Re: terminology confusion - component/dependent
C02150 00418 ∂29-Dec-86 1830 Bobrow.pa@Xerox.COM Re: terminology confusion: Specifying Builtin classes
C02153 00419 ∂29-Dec-86 1832 Bobrow.pa@Xerox.COM Re: terminology confusion
C02158 00420 ∂29-Dec-86 1830 Bobrow.pa@Xerox.COM Re: terminology confusion STRUCTURE-CLASS as a BUILT-IN-CLASS?
C02161 00421 ∂29-Dec-86 2111 RPG Terminology
C02164 00422 ∂29-Dec-86 2157 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: terminology confusion
C02169 00423 ∂29-Dec-86 2207 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: terminology confusion: Specifying Builtin classes
C02174 00424 ∂29-Dec-86 2220 Masinter.pa@Xerox.COM Comments on various comments
C02180 00425 ∂29-Dec-86 2226 RPG Re: Terminology
C02182 00426 ∂30-Dec-86 1033 Bobrow.pa@Xerox.COM Re: Comments on various comments
C02188 00427 ∂30-Dec-86 1033 Bobrow.pa@Xerox.COM Re: terminology confusion
C02190 00428 ∂30-Dec-86 1035 RPG Re: Terminology
C02192 00429 ∂30-Dec-86 1034 Bobrow.pa@Xerox.COM Re: Terminology
C02194 00430 ∂30-Dec-86 1034 Bobrow.pa@Xerox.COM Re: Issues in Concepts chapter
C02196 00431 ∂30-Dec-86 1037 RPG Re: Terminology
C02198 00432 ∂30-Dec-86 1036 RPG Re: Terminology
C02200 00433 ∂30-Dec-86 1033 Bobrow.pa@Xerox.COM Re: terminology confusion: Specifying Builtin classes
C02203 00434 ∂30-Dec-86 1126 RPG Terminology (sort of): A New Question
C02204 00435 ∂30-Dec-86 1139 Moon@STONY-BROOK.SCRC.Symbolics.COM Terminology: default value form
C02206 00436 ∂30-Dec-86 1215 Masinter.pa@Xerox.COM Re: Terminology
C02208 00437 ∂30-Dec-86 1214 Masinter.pa@Xerox.COM Re: Comments on various comments
C02214 00438 ∂30-Dec-86 1236 RPG Clarfication on ``superclass''
C02215 00439 ∂30-Dec-86 1332 Bobrow.pa@Xerox.COM Re: Terminology: default value form
C02218 00440 ∂30-Dec-86 1332 Bobrow.pa@Xerox.COM Re: Clarfication on ``superclass''
C02220 00441 ∂30-Dec-86 1620 Dussud%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Terminology (sort of): A New Question
C02222 00442 ∂30-Dec-86 2149 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Terminology: default value form
C02225 00443 ∂30-Dec-86 2152 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Terminology: default value form
C02229 00444 ∂30-Dec-86 2204 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Comments on various comments
C02233 00445 ∂31-Dec-86 1514 RPG STANDARD-TYPE-CLASS
C02238 00446 ∂31-Dec-86 1529 Bobrow.pa@Xerox.COM Re: make-method issue
C02240 00447 ∂31-Dec-86 1529 Bobrow.pa@Xerox.COM Re: :allocation slot-option issues
C02246 00448 ∂31-Dec-86 1529 Bobrow.pa@Xerox.COM Re: :allocation slot-option issues
C02252 00449 ∂31-Dec-86 1726 Bobrow.pa@Xerox.COM Method Combination Proposal
C02275 00450 ∂02-Jan-87 2231 RPG Class Precedence List
C02288 00451 ∂03-Jan-87 1529 Moon@STONY-BROOK.SCRC.Symbolics.COM STANDARD-TYPE-CLASS
C02290 00452 ∂03-Jan-87 1537 Moon@STONY-BROOK.SCRC.Symbolics.COM Terminology: lattice
C02292 00453 ∂03-Jan-87 1600 Moon@STONY-BROOK.SCRC.Symbolics.COM terminology confusion: subclass, superclass
C02306 00454 ∂03-Jan-87 1749 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: :allocation slot-option issues
C02316 00455 ∂03-Jan-87 1835 RPG Terminology
C02318 00456 ∂04-Jan-87 1251 RPG Very Dull Message About Class Precedence Lists
C02326 00457 ∂05-Jan-87 0857 Bobrow.pa@Xerox.COM Re: terminology confusion: subclass, superclass
C02329 00458 ∂05-Jan-87 0956 Bobrow.pa@Xerox.COM Re: Class Precedence List
C02332 00459 ∂05-Jan-87 0957 Bobrow.pa@Xerox.COM Re: STANDARD-TYPE-CLASS
C02335 00460 ∂05-Jan-87 1150 Bobrow.pa@Xerox.COM Re: :allocation slot-option issues
C02342 00461 ∂05-Jan-87 1151 Gregor.pa@Xerox.COM Re: STANDARD-TYPE-CLASS
C02345 00462 ∂05-Jan-87 1150 Bobrow.pa@Xerox.COM Some invariants
C02348 00463 ∂05-Jan-87 1216 DLW@ALDERAAN.SCRC.Symbolics.COM Re: Class Precedence List
C02351 00464 ∂05-Jan-87 1233 Moon@STONY-BROOK.SCRC.Symbolics.COM Method Combination Proposal
C02373 00465 ∂05-Jan-87 1237 Moon@STONY-BROOK.SCRC.Symbolics.COM Method Combination Proposal
C02396 00466 ∂05-Jan-87 1246 Gregor.pa@Xerox.COM Re: Question about MAKE-METHOD Arguments
C02399 00467 ∂05-Jan-87 1326 Gregor.pa@Xerox.COM Re: Terminology: default value form
C02402 00468 ∂05-Jan-87 1326 Gregor.pa@Xerox.COM Re: MAKE-METHOD arguments discussion
C02405 00469 ∂05-Jan-87 1351 Gregor.pa@Xerox.COM Re: Comments on various comments
C02409 00470 ∂05-Jan-87 1359 Gregor.pa@Xerox.COM Re: STANDARD-TYPE-CLASS
C02413 00471 ∂05-Jan-87 2034 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: MAKE-METHOD arguments discussion
C02417 00472 ∂05-Jan-87 2129 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: :allocation slot-option issues
C02419 00473 ∂05-Jan-87 2154 Moon@STONY-BROOK.SCRC.Symbolics.COM Class Precedence List
C02427 00474 ∂06-Jan-87 0141 Bobrow.pa@Xerox.COM Re: :allocation slot-option issues
C02430 00475 ∂06-Jan-87 0156 Bobrow.pa@Xerox.COM Re: Class Precedence List
C02447 00476 ∂06-Jan-87 0250 Bobrow.pa@Xerox.COM Re: Method Combination Proposal
C02456 00477 ∂06-Jan-87 0822 Dussud%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Some invariants
C02459 00478 ∂06-Jan-87 1123 Moon@RIVERSIDE.SCRC.Symbolics.COM Re: :allocation slot-option issues
C02462 00479 ∂06-Jan-87 1435 Gregor.pa@Xerox.COM Re: MAKE-METHOD arguments discussion
C02469 00480 ∂06-Jan-87 1900 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Method Combination Proposal
C02488 00481 ∂07-Jan-87 1737 Gregor.pa@Xerox.COM Re: Method Combination Proposal
C02493 00482 ∂07-Jan-87 1737 Masinter.pa@Xerox.COM Re: Some invariants
C02495 00483 ∂07-Jan-87 1737 Masinter.pa@Xerox.COM Re: Some invariants
C02497 00484 ∂07-Jan-87 1758 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Some invariants
C02499 00485 ∂07-Jan-87 1841 Masinter.pa@Xerox.COM Re: Some invariants
C02502 00486 ∂07-Jan-87 1928 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Some invariants
C02505 00487 ∂07-Jan-87 2134 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Method Combination Proposal
C02518 00488 ∂08-Jan-87 1701 Moon@STONY-BROOK.SCRC.Symbolics.COM Lexical environment of slot default initial value forms
C02522 00489 ∂08-Jan-87 1714 RPG What's left to do
C02523 00490 ∂08-Jan-87 1952 Moon@STONY-BROOK.SCRC.Symbolics.COM What's left to do
C02526 00491 ∂08-Jan-87 2001 RPG Class Precedence List
C02540 00492 ∂08-Jan-87 2028 Moon@STONY-BROOK.SCRC.Symbolics.COM Issues for the CLOS committee to start focussing on
C02547 00493 ∂08-Jan-87 2057 Dussud%Jenner%ti-csl.csnet@RELAY.CS.NET Re: MAKE-METHOD arguments discussion
C02553 00494 ∂08-Jan-87 2132 Bobrow.pa@Xerox.COM Re: What's left to do
C02555 00495 ∂08-Jan-87 2321 Bobrow.pa@Xerox.COM Re: Method Combination Proposal
C02568 00496 ∂08-Jan-87 2341 Bobrow.pa@Xerox.COM Re: Class Precedence List
C02572 00497 ∂08-Jan-87 2342 Bobrow.pa@Xerox.COM Re: Lexical environment of slot default initial value forms
C02574 00498 ∂08-Jan-87 2349 Bobrow.pa@Xerox.COM Re: Issues for the CLOS committee to start focussing on
C02577 00499 ∂09-Jan-87 0612 skeene@STONY-BROOK.SCRC.Symbolics.COM Re: Issues for the CLOS committee to start focussing on
C02579 00500 ∂09-Jan-87 1154 RPG Class Precedence List: Rebuttal to Danny
C02590 00501 ∂09-Jan-87 1349 Moon@RIVERSIDE.SCRC.Symbolics.COM Re: What's left to do
C02593 00502 ∂09-Jan-87 1359 skeene@RIVERSIDE.SCRC.Symbolics.COM new version of concepts chapter
C02595 00503 ∂09-Jan-87 1744 Bobrow.pa@Xerox.COM Re: Class Precedence List: Rebuttal to Danny
C02604 00504 ∂10-Jan-87 2101 RPG For the Record
C02607 00505 ∂11-Jan-87 1207 RPG Issues for the CLOS committee to start focussing on
C02612 00506 ∂11-Jan-87 1208 RPG Environment for initial value form
C02613 00507 ∂11-Jan-87 2230 Bobrow.pa@Xerox.COM Re: Issues for the CLOS committee to start focussing on
C02616 00508 ∂11-Jan-87 2240 Bobrow.pa@Xerox.COM Re: For the Record
C02619 00509 ∂11-Jan-87 2323 RPG CPL Algorithm
C02623 00510 ∂12-Jan-87 0028 Bobrow.pa@Xerox.COM Re: CPL Algorithm
C02625 00511 ∂12-Jan-87 1531 Moon@RIVERSIDE.SCRC.Symbolics.COM Documents updated for method combination
C02628 00512 ∂12-Jan-87 1547 Moon@RIVERSIDE.SCRC.Symbolics.COM Re: Method Combination Proposal
C02646 00513 ∂12-Jan-87 1828 Moon@STONY-BROOK.SCRC.Symbolics.COM For the Record
C02649 00514 ∂12-Jan-87 1836 Moon@STONY-BROOK.SCRC.Symbolics.COM Environment for initial value form
C02651 00515 ∂12-Jan-87 1945 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Issues for the CLOS committee to start focussing on
C02653 00516 ∂12-Jan-87 1950 Moon@STONY-BROOK.SCRC.Symbolics.COM For the Record
C02655 00517 ∂13-Jan-87 1045 Bobrow.pa@Xerox.COM Re: Issues for the CLOS committee to start focussing on
C02658 00518 ∂13-Jan-87 2046 skeene@RIVERSIDE.SCRC.Symbolics.COM Re: Issues for the CLOS committee to start focussing on
C02661 00519 ∂15-Jan-87 0837 skeene@STONY-BROOK.SCRC.Symbolics.COM draft on inheritance of slots and defclass options
C02676 00520 ∂15-Jan-87 1514 Gregor.pa@Xerox.COM Re: Issues for the CLOS committee to start focussing on
C02678 00521 ∂15-Jan-87 1713 Masinter.pa@Xerox.COM Re: draft on inheritance of slots and defclass options
C02681 00522 ∂16-Jan-87 0748 skeene@STONY-BROOK.SCRC.Symbolics.COM Re: draft on inheritance of slots and defclass options
C02686 00523 ∂16-Jan-87 0821 skeene@STONY-BROOK.SCRC.Symbolics.COM new versions of files
C02689 00524 ∂19-Jan-87 2142 Moon@MEAD.SCRC.Symbolics.COM change-class and class redefinition
C02709 00525 ∂20-Jan-87 1010 DLW@ALDERAAN.SCRC.Symbolics.COM change-class and class redefinition
C02713 00526 ∂20-Jan-87 1224 Bobrow.pa@Xerox.COM New version of define-method-combination
C02737 00527 ∂20-Jan-87 1429 Gregor.pa@Xerox.COM Re: New version of define-method-combination
C02743 00528 ∂21-Jan-87 1421 RPG standard-type-classes
C02747 00529 ∂21-Jan-87 1632 kempf%hplabsc@hplabs.HP.COM Re: standard-type-classes
C02749 00530 ∂21-Jan-87 1755 Gregor.pa@Xerox.COM Re: change-class and class redefinition
C02753 00531 ∂21-Jan-87 1755 Bobrow.pa@Xerox.COM Small additional suggestion wrt Method-combination
C02755 00532 ∂21-Jan-87 2010 RPG Inheritance of Methods
C02757 00533 ∂21-Jan-87 2200 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: change-class and class redefinition
C02766 00534 ∂21-Jan-87 2248 masinter.pa@Xerox.COM Re: standard-type-classes
C02770 00535 ∂22-Jan-87 0810 skeene@STONY-BROOK.SCRC.Symbolics.COM Inheritance of Methods
C02774 00536 ∂22-Jan-87 1140 Masinter.pa@Xerox.COM [Masinter.pa: Handling Common Lisp built in types]
C02782 00537 ∂22-Jan-87 1140 Masinter.pa@Xerox.COM Re: Inheritance of Methods
C02784 00538 ∂22-Jan-87 1527 Bobrow.pa@Xerox.COM Re: Inheritance of Methods
C02786 00539 ∂22-Jan-87 1527 Bobrow.pa@Xerox.COM Re: standard-type-classes
C02789 00540 ∂22-Jan-87 1527 Bobrow.pa@Xerox.COM Re: change-class and class redefinition
C02795 00541 ∂22-Jan-87 1527 Bobrow.pa@Xerox.COM [Gregor Kiczales <Gregor.pa>: Re: STANDARD-TYPE-CLASS]
C02799 00542 ∂22-Jan-87 1556 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: standard-type-classes
C02802 00543 ∂22-Jan-87 1603 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Inheritance of Methods
C02804 00544 ∂22-Jan-87 1603 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: change-class and class redefinition
C02810 00545 ∂22-Jan-87 1610 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Inheritance of Methods
C02813 00546 ∂22-Jan-87 1642 Masinter.pa@Xerox.COM Re: Inheritance of Methods
C02815 00547 ∂22-Jan-87 1654 Bobrow.pa@Xerox.COM Re: standard-type-classes
C02818 00548 ∂22-Jan-87 1700 Bobrow.pa@Xerox.COM Re: change-class and class redefinition
C02821 00549 ∂22-Jan-87 1701 RPG Inheritance of Methods
C02823 00550 ∂22-Jan-87 2201 Masinter.pa@Xerox.COM Re: standard-type-classes
C02826 00551 ∂23-Jan-87 1123 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: standard-type-classes
C02830 00552 ∂23-Jan-87 1125 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Inheritance of Methods
C02832 00553 ∂23-Jan-87 1131 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: change-class and class redefinition
C02835 00554 ∂23-Jan-87 1141 Gregor.pa@Xerox.COM Re: standard-type-classes
C02838 00555 ∂23-Jan-87 1142 Gregor.pa@Xerox.COM Re: change-class and class redefinition
C02841 00556 ∂23-Jan-87 1204 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: change-class and class redefinition
C02844 00557 ∂23-Jan-87 1236 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: standard-type-classes
C02846 00558 ∂23-Jan-87 1241 RPG Strenuously
C02847 00559 ∂23-Jan-87 1350 Moon@STONY-BROOK.SCRC.Symbolics.COM Symbolics design review
C02853 00560 ∂23-Jan-87 2139 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
C02862 00561 ∂24-Jan-87 1528 RPG Alternatives
C02864 00562 ∂25-Jan-87 1530 Moon@STONY-BROOK.SCRC.Symbolics.COM Comments on Concepts chapter 1/23/87
C02890 00563 ∂25-Jan-87 1652 RPG Moon's comments
C02897 00564 ∂25-Jan-87 1840 Moon@RIVERSIDE.SCRC.Symbolics.COM Gabriel's comments
C02909 00565 ∂25-Jan-87 2157 Moon@STONY-BROOK.SCRC.Symbolics.COM Class-precedence-list computation
C02917 00566 ∂26-Jan-87 1413 Gregor.pa@Xerox.COM symbols are not generic functions
C02920 00567 ∂26-Jan-87 1413 Bobrow.pa@Xerox.COM Re: ---
C02924 00568 ∂26-Jan-87 1605 kahn.pa@Xerox.COM :allocation :none
C02927 00569 ∂26-Jan-87 2056 Moon@STONY-BROOK.SCRC.Symbolics.COM Class-precedence-list computation
C02931 00570 ∂26-Jan-87 2127 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: change-class and class redefinition
C02934 00571 ∂27-Jan-87 0027 RPG CPL Update
C02936 00572 ∂27-Jan-87 0927 Bobrow.pa@Xerox.COM Re: CPL Update
C02941 00573 ∂27-Jan-87 1112 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: ---
C02947 00574 ∂27-Jan-87 1207 RPG CPL Computation
C02960 00575 ∂27-Jan-87 1430 Bobrow.pa@Xerox.COM Re: CPL Computation
C02964 00576 ∂27-Jan-87 1432 Bobrow.pa@Xerox.COM Re: ---
C02968 00577 ∂27-Jan-87 1752 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: ---
C02972 00578 ∂27-Jan-87 1801 RPG Elaboration on the Non-intuitiveness of New Flavors Algorithm...
C02978 00579 ∂27-Jan-87 1805 Bobrow.pa@Xerox.COM Re: CPL Update
C02983 00580 ∂27-Jan-87 1854 Bobrow.pa@Xerox.COM Re: ---
C02986 00581 ∂27-Jan-87 1857 Bobrow.pa@Xerox.COM Re: Elaboration on the Non-intuitiveness of New Flavors
C02988 00582 ∂27-Jan-87 1914 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: ---
C02993 00583 ∂27-Jan-87 2003 Moon@RIVERSIDE.SCRC.Symbolics.COM :allocation :none
C02997 00584 ∂27-Jan-87 2011 Moon@RIVERSIDE.SCRC.Symbolics.COM symbols are not generic functions
C03002 00585 ∂27-Jan-87 2116 Moon@STONY-BROOK.SCRC.Symbolics.COM Danny's new version of define-method-combination
C03022 00586 ∂27-Jan-87 2117 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: ---
C03026 00587 ∂27-Jan-87 2222 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: CPL Update
C03029 00588 ∂27-Jan-87 2234 Moon@STONY-BROOK.SCRC.Symbolics.COM CPL Computation
C03032 00589 ∂28-Jan-87 0713 DLW@ALDERAAN.SCRC.Symbolics.COM :allocation :none
C03036 00590 ∂28-Jan-87 1005 RPG Complexity of Topological Sort + single-pass treewalk tiebreaker
C03037 00591 ∂28-Jan-87 1754 Bobrow.pa@Xerox.COM Re: Method Combination
C03056 00592 ∂28-Jan-87 1922 RPG Last-Visited Preorder
C03058 00593 ∂28-Jan-87 1932 RPG Progress is Our Most Important Problem
C03061 00594 ∂28-Jan-87 2216 Moon@STONY-BROOK.SCRC.Symbolics.COM Elaboration on the Non-intuitiveness of New Flavors Algorithm...
C03066 00595 ∂29-Jan-87 0206 RPG CPL Tiebreaker
C03071 00596 ∂29-Jan-87 0702 skeene@STONY-BROOK.SCRC.Symbolics.COM Progress is Our Most Important Problem
C03078 00597 ∂29-Jan-87 1047 Bobrow.pa@Xerox.COM Re: Last-Visited Preorder
C03081 00598 ∂29-Jan-87 1048 Bobrow.pa@Xerox.COM Re: Progress is Our Most Important Problem
C03086 00599 ∂29-Jan-87 1402 skeene@STONY-BROOK.SCRC.Symbolics.COM changes made to documentation
C03089 00600 ∂29-Jan-87 1652 RPG The Real Deadline
C03091 00601 ∂29-Jan-87 1708 "Patrick H Dussud %Jenner%ti-csl.csnet"@RELAY.CS.NET Re: Method Combination
C03099 00602 ∂29-Jan-87 1713 Gregor.pa@Xerox.COM Re: Progress is Our Most Important Problem -- Method
C03102 00603 ∂29-Jan-87 1722 RPG Re: Algorithms
C03105 00604 ∂29-Jan-87 1713 Gregor.pa@Xerox.COM My comments on some things
C03113 00605 ∂29-Jan-87 1713 Gregor.pa@Xerox.COM Re: symbols are not generic functions
C03117 00606 ∂29-Jan-87 1930 Moon@STONY-BROOK.SCRC.Symbolics.COM CPL Tiebreaker
C03124 00607 ∂29-Jan-87 2003 Moon@STONY-BROOK.SCRC.Symbolics.COM Gregor's comments on some things
C03133 00608 ∂29-Jan-87 2154 Moon@STONY-BROOK.SCRC.Symbolics.COM Minor things noticed while proofreading documents
C03136 00609 ∂30-Jan-87 2218 RPG CPL etc
C03144 00610 ∂31-Jan-87 0923 RPG Common Lisp Types
C03148 00611 ∂31-Jan-87 1156 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: symbols are not generic functions
C03156 00612 ∂31-Jan-87 2054 Moon@STONY-BROOK.SCRC.Symbolics.COM Moon/Bobrow phone conversation
C03159 00613 ∂31-Jan-87 2127 Moon@STONY-BROOK.SCRC.Symbolics.COM CPL etc
C03166 00614 ∂01-Feb-87 1410 RPG CPL Varia
C03169 00615 ∂01-Feb-87 2257 edsel!bhopal!jonl@navajo.stanford.edu CPL anxieties
C03176 00616 ∂02-Feb-87 0854 RPG Re: ---
C03179 ENDMK
C⊗;
∂04-Sep-86 2153 Owners-CommonLoopsCore↑.pa@Xerox.COM Whoppers and run-super
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Sep 86 21:50:35 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 04 SEP 86 21:48:11 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa@XEROX.ARPA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 04 SEP 86 21:47:42 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 74741;
Fri 5-Sep-86 00:46:12 EDT
Date: Fri, 5 Sep 86 00:46 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Whoppers and run-super
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860902-183338-1341@Xerox>
Message-ID: <860905004612.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 2 Sep 86 18:33 PDT
From: Bobrow.pa@Xerox.COM
Sorry about the slow response; I spent a lot of time thinking about this
instead of sending some sort of knee-jerk instant response.
There seems to be a lot in common between whoppers and the Loops use of
run-super. I have been trying to work out the appropriate relation
between run-super and daemon method combination with whoppers.
Whoppers are not expressible in the method combination language.
This is not completely true. They could easily be done in the method
combination language. We chose to do them instead as a separate layer
for the following reasons:
(1) We wanted the behavior of whoppers and wrappers to be constant,
independent of the method-combination type.
(2) We found that in old flavors having to worry about whoppers and
wrappers greatly complicated the definition of each method-combination
type. It seemed better to do it in a central place and get it out
of the way of the user who wants to define his own method combination.
(3) Whoppers and wrappers seem to us to be fundamentally different
from ordinary methods; in particular, they receive different arguments.
Wrappers, being macros, receive forms as arguments rather than receiving
the arguments of a generic function call. Less obviously, whoppers
receive different arguments; the continuation used by CONTINUE-WHOPPER
is passed to the whopper as two additional arguments that are added to
the lambda-list by defwhopper (never mind why it's two arguments instead
of one, that's a minor implementation detail.) There are efficiency
issues, discussed much later in this message, that make us wish to keep
whoppers separate from ordinary methods so as not to slow down ordinary
methods.
(4) I don't like :around methods for the irrelevant reason that Stallman's
flavor system has them and he misimplemented them in a way that appears
especially ugly to the user. Too much of the implementation mechanism
shows through.
None of these reasons is ineluctably compelling, and we could instead
have chosen to make DEFINE-METHOD-COMBINATION insert into the body a call
to a function to take care of the wrappers and whoppers, and then have
provided an option to turn this off and let the method-combination type
take direct control. I don't see a lot of benefit from this; what would
be accomplished by taking direct control other than surprising the user
by making wrappers and whoppers behave in an unexpected way? Maybe there
is something that I am not seeing.
Neither is run-super. I believe both could be fixed by adding a new
standard form corresponding to call-component-methods.
call-first-with-continuations <list-of-methods>
calls the first on the list, and makes available the list for the called
method. If run-super is invoked in the method, it does:
(call-first-with-continuations (cdr list-of-methods))
If continue-whopper we spell "run-super", and whopper as ":around", then
super-daemon method combination (allowing run-super in primary methods)
is defined by something like
(define-method-combination :super-daemon
((around "around" :every :base-flavor-last (:around))
(before "before" :every :base-flavor-last (:before))
(primary "primary" :every :base-flavor-last (:primary))
(after "after" :every :base-flavor-first (:after)))
(call-first-with-continuations
'(,. around
(multiple-value-prog2
(call-component-methods , before)
(call-first-with-continuations ',primary)
(call-component-methods ,after)))
This makes run-super be a feature of method-combination with
call-first-with-continuations only. It has the same model as it has in
Loops and Smalltalk, and computable at method-definition time.
Don't forget that continue-whopper allows changing the arguments that
are passed on to the continuation, whereas run-super does not. This can
be important sometimes. I think that's orthogonal to the rest of the
discussion, however.
I have not thought through a best implementation. An obvious one is to
bind the continuation list of functions in a special variable.
Does this make sense? It seems to provide a single coherent story.
There is no question that something along these lines, with the typos
and bugs taken out, could work. For example, the following code works
in New Flavors (more comments follow the code):
(DEFVAR *SUPERCLASS-CONTINUATIONS*)
(DEFUN RUN-SUPER ()
(FUNCALL (POP *SUPERCLASS-CONTINUATIONS*)))
(DEFUN CALL-FIRST-WITH-CONTINUATIONS (FORMS)
(IF (REST FORMS)
`(STACK-LET ((*SUPERCLASS-CONTINUATIONS*
(LIST ,@(MAPCAR (LAMBDA (FORM)
`(LAMBDA ()
(DECLARE (SYS:DOWNWARD-FUNCTION))
,FORM))
(REST FORMS)))))
,(FIRST FORMS))
(FIRST FORMS)))
(DEFINE-METHOD-COMBINATION :SUPER-DAEMON ()
((AROUND "around" :EVERY :MOST-SPECIFIC-FIRST (:AROUND))
(BEFORE "before" :EVERY :MOST-SPECIFIC-FIRST (:BEFORE))
(PRIMARY "primary" :EVERY :MOST-SPECIFIC-FIRST () :DEFAULT)
(AFTER "after" :EVERY :MOST-SPECIFIC-LAST (:AFTER)))
(CALL-FIRST-WITH-CONTINUATIONS
(NCONC (MAPCAR #'CALL-COMPONENT-METHOD AROUND)
`((MULTIPLE-VALUE-PROG2
,(CALL-COMPONENT-METHODS BEFORE)
,(CALL-FIRST-WITH-CONTINUATIONS
(MAPCAR #'CALL-COMPONENT-METHOD PRIMARY))
,(CALL-COMPONENT-METHODS AFTER))))))
(DEFGENERIC SDTEST (X Y)
(:METHOD-COMBINATION :SUPER-DAEMON))
(DEFFLAVOR SDTEST1 () ())
(DEFFLAVOR SDTEST2 () (SDTEST1))
(DEFFLAVOR SDTEST3 () (SDTEST2))
(DEFMETHOD (SDTEST SDTEST1) (X)
(LIST 1 X))
(DEFMETHOD (SDTEST SDTEST2) (X)
(DECLARE (IGNORE X))
(CONS 2 (RUN-SUPER)))
(DEFMETHOD (SDTEST SDTEST3) (X)
(DECLARE (IGNORE X))
(CONS 3 (RUN-SUPER)))
(DEFMETHOD (SDTEST SDTEST2 :AROUND) (X)
(LIST "[" (RUN-SUPER) "|" X "]"))
(SDTEST (MAKE-INSTANCE 'SDTEST3) 105)
; => ("[" (3 2 1 105) "|" 105 "]")
This implementation could use some additional error checking. More importantly,
it contains a serious bug. The dynamic scoping of *SUPERCLASS-CONTINUATIONS*
means that incorrect results can occur when closures from two different generic
function invocations are calling each other. To get correct operation, the
continuation must be lexically scoped. If this sounds esoteric, consider the
following example, which has been taken from a real-life program:
(defmethod print-object :around ((object italicized-object) stream)
(with-character-face (:italic stream)
(run-super))
which makes any object of class italicized-object print itself in italics.
With-character-face is just a macro that makes output to the given stream
appear in the given face while executing its body.
This looks fine until you expand the with-character-face macro, which
expands into [the following is simplified from what it actually expands
into in Genera]
(with-style-internal stream ':italic
(lambda (stream) (run-super)))
where with-style-internal is a generic function handled by
a stream method that sets up for italic characters and calls
back into the lambda. If the handling of with-style-internal
also involves :around methods, *SUPERCLASS-CONTINUATIONS* will
be bound and the run-super inside the lambda will call a
with-style-internal method instead of a print-object method.
No good.
Lexically scoping the continuation is possible in New Flavors also.
An extra argument has to be inserted into the arglist of any method
that uses run-super, to receive the continuation, since it can no
longer be passed behind the lambda-list's back in a special variable,
and this code transformation makes everything a little more complicated.
Here is the working, tested code (more comments after the code):
(DEFUN RUN-SUPER ()
(ERROR "RUN-SUPER not called from a proper lexical environment."))
;;; Call a method, passing the continuation before the regular arguments
(DEFUN CALL-COMPONENT-METHOD-WITH-CONTINUATION (METHOD CONTINUATION-FORM ARGS)
(CALL-COMPONENT-METHOD METHOD
:ARGLIST (LIST `(LAMBDA ()
(DECLARE (SYS:DOWNWARD-FUNCTION))
,CONTINUATION-FORM)
ARGS)
:APPLY T))
;;; Call a sequence of methods, each with a continuation that calls the next
;;; method. The continuation of the last method is the second argument.
(DEFUN CALL-COMPONENT-METHODS-WITH-CONTINUATION (METHODS CONTINUATION-FORM ARGS)
(IF METHODS
(CALL-COMPONENT-METHOD-WITH-CONTINUATION
(FIRST METHODS)
(CALL-COMPONENT-METHODS-WITH-CONTINUATION
(REST METHODS) CONTINUATION-FORM ARGS)
ARGS)
CONTINUATION-FORM))
(DEFINE-METHOD-COMBINATION :SUPER-DAEMON-2 ()
((AROUND "around" :EVERY :MOST-SPECIFIC-FIRST (:AROUND))
(BEFORE "before" :EVERY :MOST-SPECIFIC-FIRST (:BEFORE))
(PRIMARY "primary" :EVERY :MOST-SPECIFIC-FIRST () :DEFAULT)
(AFTER "after" :EVERY :MOST-SPECIFIC-LAST (:AFTER)))
(:METHOD-TRANSFORMER
;; Insert continuation argument into methods that can call RUN-SUPER
(:METHOD-ARGLIST
(IF (MEMBER (METHOD-OPTIONS FUNCTION-SPEC)
'((:AROUND) () (:DEFAULT))
:TEST #'EQUAL)
(CONS 'RUN-SUPER-CONTINUATION METHOD-ARGLIST)
METHOD-ARGLIST))
;; Change arglist used for error-checking correspondingly
(:GENERIC-METHOD-ARGLIST
(IF (MEMBER (METHOD-OPTIONS FUNCTION-SPEC)
'((:AROUND) () (:DEFAULT))
:TEST #'EQUAL)
(LIST* (FIRST GENERIC-METHOD-ARGLIST)
'RUN-SUPER-CONTINUATION
(REST GENERIC-METHOD-ARGLIST))
GENERIC-METHOD-ARGLIST))
;; Define RUN-SUPER macro locally in the body of such methods
(:METHOD-BODY
(IF (MEMBER (METHOD-OPTIONS FUNCTION-SPEC)
'((:AROUND) () (:DEFAULT))
:TEST #'EQUAL)
(MULTIPLE-VALUE-BIND (DECLARATIONS BODY)
(SI:FIND-BODY-DECLARATIONS METHOD-BODY NIL)
`(,@DECLARATIONS
(IGNORE RUN-SUPER-CONTINUATION)
(MACROLET ((RUN-SUPER ()
`(FUNCALL RUN-SUPER-CONTINUATION)))
,@BODY)))
METHOD-BODY)))
(:ARGLIST IGNORE &REST ARGS)
(CALL-COMPONENT-METHODS-WITH-CONTINUATION
AROUND
`(MULTIPLE-VALUE-PROG2
,(CALL-COMPONENT-METHODS BEFORE)
,(CALL-COMPONENT-METHODS-WITH-CONTINUATION
PRIMARY
`(ERROR "RUN-SUPER past the least-specific method")
ARGS)
,(CALL-COMPONENT-METHODS AFTER))
ARGS))
(DEFGENERIC SDTEST-2 (X Y)
(:METHOD-COMBINATION :SUPER-DAEMON-2))
(DEFFLAVOR SDTEST1 () ())
(DEFFLAVOR SDTEST2 () (SDTEST1))
(DEFFLAVOR SDTEST3 () (SDTEST2))
(DEFMETHOD (SDTEST-2 SDTEST1) (X)
(LIST 1 X))
(DEFMETHOD (SDTEST-2 SDTEST2) (X)
(DECLARE (IGNORE X))
(CONS 2 (RUN-SUPER)))
(DEFMETHOD (SDTEST-2 SDTEST3) (X)
(DECLARE (IGNORE X))
(CONS 3.0 (RUN-SUPER)))
(DEFMETHOD (SDTEST-2 SDTEST2 :AROUND) (X)
(LIST "[" (RUN-SUPER) "|" X "]"))
(SDTEST-2 (MAKE-INSTANCE 'SDTEST3) 105)
; => ("[" (3.0 2 1 105) "|" 105 "]")
I wouldn't want to make either of these the default, because of the
efficiency cost of all this extra mechanism. This is based on my
prejudice that "normal" programs won't use run-super and shouldn't have
to pay the cost of keeping around the information needed for run-super
to work. With modest amounts of additional hair in the
:method-transformer, it should be possible to scan the body of the
method for calls to run-super, and generate different code if it is not
present. It's midnight, though, so I'm going to stop here.
In conclusion: yes, it's possible to do run-super this way, and
presumably it works about as well as any other way of doing run-super.
Yes, it's possible to do whoppers this way, and they work about as well
as any other way of doing whoppers. You can't do wrappers exactly this
way, since they are macros rather than functions, but there is certainly
no inherent reason that code for wrappers couldn't be written into a
define-method-combination, too. The big difference between doing these
things this way and doing them the way New Flavors does it now is
primarily that the expensive continuation-passing mechanisms needed to
make whoppers/run-super work are invoked explicitly by using a different
special form to define a whopper than to define a method, instead of
implicitly by calling run-super somewhere in the body of the method, and
secondarily that the hair for wrappers and whoppers is kept hidden from
the user who just wants to define a new type of method-combination
without having to worry about anything complicated.
∂04-Sep-86 2226 Owners-commonloopscore↑.pa@Xerox.COM Varia
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Sep 86 22:26:27 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 04 SEP 86 22:25:31 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 04 SEP 86
22:25:18 PDT
Date: 04 Sep 86 22:25 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: Varia
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860904-222531-1191@Xerox>
We want to distinguish the type hierarchy from the class lattice.
Therefore, in messages where I say `argument specifier,' I am
not, as Moon suggests, making a typo for `type specifier.'
`Instance of a class' is different from `instance of a flavor' or
`instance of a defstruct.' We've made a parallel class lattice
corresponding to the type hierarchy in CLtL. We decided (today) to flush
ATOM and COMMON from that lattice (vector is an atom). Therefore, a cons
cell is an instance of the CONS class. Because the metaclass of a CONS
cell is not the class CLASS (but is BUILT-IN-CLASS or some such) its
interpretation as an instance is different from that of an instance
meta-class is CLASS. Everything in Common Lisp is an instance of some
class.
Danny and I go around daily on the disposition of method selection.
We now have yet another proposal for it. In this one this example
does what DLW expects:
(let ((*standard-output* <instance of hairy-display-hardware>))
(print foo))
Because the generic function PRINT has as function parameters:
(object &optional (stream *standard-output*))
Defmethods cannot default unsupplied arguments. Danny's message will
present this new version. (I'm too burned to do it.)
I'm fresh enough, though, to present why I don't like defmethods
creating generic functions. In my view, a generic function is
something that responds T to (typep <gf> 'function). It has other
information within itself. It has no name but can be associated with
a name, just as in
(defun foo (x) ...)
the thing in the symbol-function cell has no name but is associated with
the name `FOO.' The parts of the generic function are the discriminating
function, the methods, the function parameters, various class pointers,
and etc. Usually the methods are stored as part of the method object.
Defmethod adds another method to a generic function. That is, it adds a
new subpart to an existing thing. It seems odd to me that adding a new
subpart should create the thing of which it is to become a part. There is
a dimension whose extremity is absolute insanity, and the current proposal
to allow defmethod to create the superpart has a non-zero component of that
dimension. An example of the insanity at the extreme in this dimension is
a possible proposal that
(setf (car x) 7)
does this
(progn
(unless (and (boundp 'x) (typep x 'cons)) (setq x (cons () ())))
(setf (car x) 7))
(Note that Lisp/VM does the equivalent of this
(setf (symbol-value <symbol>) <symbol>)
when the symbol <symbol> is interned.)
I grant we are not very far down this dimension, but why head that way?
I will be away until monday, so enjoy.
-rpg-
∂05-Sep-86 1637 Bobrow.pa@Xerox.COM Re: Defmethod syntax proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Sep 86 16:36:53 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 05 SEP 86 14:49:56 PDT
Date: 5 Sep 86 10:52 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: Defmethod syntax proposal
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 4 Sep 86 18:01 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860905-144956-1108@Xerox>
Will (defmethod generic option... lambda-list body...) be okay with
you,
or do we need to keep searching for a suitable syntax? A more real
example of the syntax would be
(defmethod turn-off-valve :before ((v master-valve))
(unless (check-with-safety-engineer v 'off)
(unsafe-operator-action "Don't do that! It will explode")))
Since all the options for method combination are either keywords or
numbers and type is not, one can distinguish the cases.
If this is not the case,
we could insist that there always be such a keyword to start.
They aren't keywords. You got fooled by looking at existing examples
where
by coincidence they were always keywords, but in general it's not
going to
work to restrict the options attached to a method to be always
keywords.
There are applications where these are names of things and the names
can
be any symbol (I think we can safely exclude nil, I hope I'm not
wrong).
Will (defmethod generic option... lambda-list body...) be okay with
you,
or do we need to keep searching for a suitable syntax?
I don't like having to put an additional item between the generic name
and the lambda-list, especially since I expect most methods to not have
any options declaration.
An alternative syntaxsuggestion:
(defmethod name-or-name-and-options lambda-list ...)
where
name-or-name-and-options = name|
(name :combination {combine-options}*)|
(name class-name {combine-options}*)
This makes it somewhat more difficult for CommonLoops type users to use
method combination. Alternatively, Flavors type use could be made
slightly more difficult by using
name-or-name-and-options = name|
(name {combine-options}*)|
(name (:class class-name) {combine-options}*)
I prefer the latter. Method combination code could process the
(:class class-name) option and change the method definition as
specified by you.
An arguments for the former is to preserve old Flavors code.
-- danny
∂05-Sep-86 1637 Owners-commonloopscore↑.pa@Xerox.COM Varia [what a useless subject!]
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Sep 86 16:37:19 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 05 SEP 86 14:53:05 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.pa@XEROX.ARPA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 05 SEP 86 14:46:41 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 75195;
Fri 5-Sep-86 16:24:21 EDT
Date: Fri, 5 Sep 86 16:24 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Varia [what a useless subject!]
To: commonloopscore↑.pa@Xerox.COM
In-Reply-To: <860904-222531-1191@Xerox>
Message-ID: <860905162420.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 04 Sep 86 22:25 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
We want to distinguish the type hierarchy from the class lattice.
I thought one of the big points of this whole affair was to do just
the opposite, i.e. to unify the type lattice and the class lattice.
Therefore, in messages where I say `argument specifier,' I am
not, as Moon suggests, making a typo for `type specifier.'
`Instance of a class' is different from `instance of a flavor' or
`instance of a defstruct.' We've made a parallel class lattice
corresponding to the type hierarchy in CLtL. We decided (today) to flush
ATOM and COMMON from that lattice (vector is an atom). Therefore, a cons
cell is an instance of the CONS class. Because the metaclass of a CONS
cell is not the class CLASS (but is BUILT-IN-CLASS or some such) its
interpretation as an instance is different from that of an instance
meta-class is CLASS. Everything in Common Lisp is an instance of some
class.
Fine, but this doesn't seem to address the terminological dilemma I was
asking about. What do we call the objects that aren't primitive, when we
need to distinguish them from the object that are primitive?
Danny and I go around daily on the disposition of method selection.
I've noticed.
We now have yet another proposal for it. In this one this example
does what DLW expects:
(let ((*standard-output* <instance of hairy-display-hardware>))
(print foo))
Because the generic function PRINT has as function parameters:
(object &optional (stream *standard-output*))
Defmethods cannot default unsupplied arguments. Danny's message will
present this new version. (I'm too burned to do it.)
I look forward to seeing it.
I'm fresh enough, though, to present why I don't like defmethods
creating generic functions. In my view, a generic function is
something that responds T to (typep <gf> 'function). It has other
information within itself. It has no name but can be associated with
a name, just as in
(defun foo (x) ...)
the thing in the symbol-function cell has no name but is associated with
the name `FOO.' The parts of the generic function are the discriminating
function, the methods, the function parameters, various class pointers,
and etc. Usually the methods are stored as part of the method object.
Defmethod adds another method to a generic function. That is, it adds a
new subpart to an existing thing. It seems odd to me that adding a new
subpart should create the thing of which it is to become a part. There is
a dimension whose extremity is absolute insanity, and the current proposal
to allow defmethod to create the superpart has a non-zero component of that
dimension. An example of the insanity at the extreme in this dimension is
a possible proposal that
(setf (car x) 7)
does this
(progn
(unless (and (boundp 'x) (typep x 'cons)) (setq x (cons () ())))
(setf (car x) 7))
(Note that Lisp/VM does the equivalent of this
(setf (symbol-value <symbol>) <symbol>)
when the symbol <symbol> is interned.)
I grant we are not very far down this dimension, but why head that way?
I understand everything you said above, but none of this talk about
implementation addresses my point, which was concerned with the concepts
that the user thinks about. Thinking about the implementation first is
not a good way to design something that is easy to use and to
understand, in my opinion.
∂05-Sep-86 1637 Bobrow.pa@Xerox.COM Re: Message selection, continued
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Sep 86 16:37:31 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 05 SEP 86 15:56:41 PDT
Date: 5 Sep 86 15:56 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: Message selection, continued
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 4 Sep 86 16:15 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860905-155641-1385@Xerox>
May I assume that everywhere you say "argument specifier" this is a
typo
for "type specifier"? Or are you really introducing a new term here?
Yes "argument specifier" is more general term than type specifier or
class specifier. It can specify, for example, that the argument must
match a particular individual. Any extensions people want to make about
specification of arguments would go here.
In yesterday's round with Gabriel and Co. we came up with the following
proposed new set of rules for message selection.
1) All uses of defmethod must be preceded by a defgeneric (but see
discussion *1 below), and the defgeneric and the defmethods must all
have congruent lambda-lists. defmethods can provide argument-specifiers
on optional arguments (but see 6 below).
2) Defgeneric can have an arbitrary lambda-list.
3) All default values for optional arguments are provided computed from
forms in the defgeneric.
4) When a generic function is called, it computes and fills in values
for any unsupplied arguments.
5) Discrimination is done on the basis of all provided and filled
values. All methods of the generic function that match are considered.
The most specific method is chosen (rules not given here).
All provided and filled in values are passed to the method.
6) Since defmethod argument list cannot have default value forms for
optionals, we make the syntax for defmethod lambda-list be:
defmethod-lambda-list:= ({required-arg}* [&optional {optional-arg}*])
optional-arg:=
var-name|
(var-name arg-specifier)
(var-name arg-specifier supplied-p-name)
The third form is provided to allow a user to supply a local name for
the supplied-p. This supplied-p is computed by the generic function, and
passed in to the method. It can then be used locally to allow the
program to override the default value provided from defgeneric. If only
a supplied-p-name is wanted, he arg-specifier T can be used to match any
argument.
*1) RPG and DLW (I believe) support the minimalist position of insisting
that the user always write the defgeneric themselves, and have it
evaluated before the defmethod. There are several increasingly
DWIM-like positions that back away from this stricture by allowing
defmethod to call defgeneric if no generic function exists.
a) If the defmethod specifies no optional arguments, then a defgenric
form is invoked with the stripped lambda list.
b) Allow the defmethod to specify optional arguments as above, and
create a stripped lambda list for the constructed defgeneric that has
only var-names for the optional arguments; that is, NIL will be provided
for the values of the optional arguments. The supplied-p portion of the
optional-arg apecification allows internal resetting of the value of the
arg if desired. If default values other than NIL are wanted, a
defgeneric form must be used.
c) Return to our previous syntax of defmethod, with
optional-arg:=
var-name|
(var-name [default-value-form [supplied-p-name]])
((var-name arg-specifier) [default-value-form [supplied-p-name]])
Construct a defgeneric from the defmethod simply stripping out the
arg-specifiers. An error is signalled if any defmethod has a
default-value-form not equal to the one found in the defgeneric. This
provides a syntactic rather than a semantic check on identity of default
values, as proposed by Moon. Again, as opposed to Moon's suggestion,
the default-values are all computed in the discriminating function, and
passed to the methods. supplied-p parameters can also be passed to the
methods from the generic function.
Proposal c also implies that every method must contain the same default
value forms, which violates some modularity. A possible fix for this is
reinterpret the naked var-name to mean unspecified default-value, or to
specify a funny value :no-default-form that can be used in that place
for optionals.
I like either (b) or (c). An argument for (c) given to me by Ken Kahn
is that users should move from defun to defmethod as a standard way to
program, even when not providing any argument specifiers. This means
that all their functions are specializable. This implies allowing a
defmethod syntax that is identical to defun, with no preceding
declaration.
-- danny
∂05-Sep-86 1638 Owners-commonloopscore↑.pa@Xerox.COM Re: Varia [what a useless subject!]
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Sep 86 16:37:48 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 05 SEP 86 16:14:38 PDT
Redistributed: commonloopscore↑.pa
Received: from Cabernet.ms by ArpaGateway.ms ; 05 SEP 86 16:13:56 PDT
Date: 5 Sep 86 16:12 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: Varia [what a useless subject!]
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 5 Sep 86 16:24 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: commonloopscore↑.pa@Xerox.COM
Message-ID: <860905-161438-1438@Xerox>
We want to distinguish the type hierarchy from the class lattice.
I thought one of the big points of this whole affair was to do just
the opposite, i.e. to unify the type lattice and the class lattice.
Right. RPG was just misguided. The Common Lisp type lattice is mapped
into the class lattice. Missing from the class lattice are uses of the
type system that are really predications. In this category we put the
type atom = (SATISFIES (NOT (CONSP X))
and common (a non-inherited feature) = (SATISFIES (MEMQ X '(CONS ...))
Why do you want to distinguish "primitive" instances from non-primitive
ones. I thought of the ugly term "non-slotted instances". Numbers have
no slots. But one can create objects with no slots using defclass. One
can also think of CONS cells as having two slots with accessors car and
cdr. Is there any thing we need to say about these items aside from
their history as Common Lisp types?
-- danny
∂05-Sep-86 1836 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Defmethod syntax proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Sep 86 18:36:12 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 05 SEP 86 17:57:09 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA@XEROX.ARPA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 05 SEP 86 17:52:25 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 75306;
Fri 5-Sep-86 20:51:17 EDT
Date: Fri, 5 Sep 86 20:51 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Defmethod syntax proposal
To: CommonLoopsCore↑.PA@Xerox.COM
In-Reply-To: <860905-144956-1108@Xerox>
Message-ID: <860905205118.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 5 Sep 86 10:52 PDT
From: Bobrow.pa@Xerox.COM
Will (defmethod generic option... lambda-list body...) be okay with you,
or do we need to keep searching for a suitable syntax?
I don't like having to put an additional item between the generic name
and the lambda-list, especially since I expect most methods to not have
any options declaration.
I think my syntax description was not clear enough. I am not proposing
that there be anything between the generic name and the lambda-list when
no options are specified. Let me give some more examples (just the
first line of each):
(defmethod turn-off-valve ((v valve))
(defmethod turn-off-valve :before ((v master-valve))
(defmethod great-scott piece environmental-impact ((x foo) (y bar))
(defmethod (turn-off-valve valve) ()
(defmethod (turn-off-valve master-valve :before) ()
(defmethod (great-scott foo piece environmental-impact) ((y bar))
An alternative syntaxsuggestion:
(defmethod name-or-name-and-options lambda-list ...)
where
name-or-name-and-options = name|
(name :combination {combine-options}*)|
(name class-name {combine-options}*)
or
name-or-name-and-options = name|
(name {combine-options}*)|
(name (:class class-name) {combine-options}*)
I prefer the latter.
Neither of these turns me on. I think whichever one involves the
"extra" word (:combination or :class) is going to discourage users
from using that style. I would rather either use the syntax
exemplified above or use different macros for defining classical
methods and general methods.
An argument for the former is to preserve old Flavors code.
Yes, one criterion I would like to preserve is that a mechanical
translation program can look at a piece of source text and reliably
classify it into CommonLoops, Flavors, or the new Common Lisp standard.
Mechanical translation tools work more smoothly for users if they
operate correctly on their own output; this makes incremental conversion
of programs a lot easier.
∂05-Sep-86 1836 Owners-commonloopscore↑.pa@Xerox.COM Terminology: instances
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Sep 86 18:36:35 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 05 SEP 86 17:58:00 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.pa@XEROX.ARPA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 05 SEP 86 17:57:20 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 75307;
Fri 5-Sep-86 20:56:10 EDT
Date: Fri, 5 Sep 86 20:56 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Terminology: instances
To: commonloopscore↑.pa@Xerox.COM
In-Reply-To: <860905-161438-1438@Xerox>
Message-ID: <860905205611.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 5 Sep 86 16:12 PDT
From: Bobrow.pa@Xerox.COM
Why do you want to distinguish "primitive" instances from non-primitive
ones. I thought of the ugly term "non-slotted instances". Numbers have
no slots. But one can create objects with no slots using defclass. One
can also think of CONS cells as having two slots with accessors car and
cdr. Is there any thing we need to say about these items aside from
their history as Common Lisp types?
See the discussion on 2-3 September about the awkwardness in Sonya's glossary
that resulted from trying to avoid making this distinction.
∂05-Sep-86 1902 Bobrow.pa@Xerox.COM [Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>:
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Sep 86 19:01:42 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 05 SEP 86 18:49:12 PDT
Date: 5 Sep 86 18:49 PDT
From: Bobrow.pa@Xerox.COM
Subject: [Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>:
Summary of features we all agree on ]
To: CommonLoopsCore↑.PA@Xerox.COM
cc: Bobrow.pa@Xerox.COM
Message-ID: <860905-184912-1633@Xerox>
Part I describes the basic tools for defining classes, methods,
generic
functions, and method combination types, and for making instances
of
classes.
DEFINING CLASSES
(DEFCLASS class-name (slot-spec...) (super-class-name...)
option...)
Not quite. We have the opposite order for (super-class-name...) and
(slot-spec...).
(DEFCLASS class-name (super-class-name...) (slot-spec...) option...)
class-name is a non-null symbol that names the class being defined.
If a
class is already defined with this name, this definition replaces
the
old definition. The default meta-class ensures that when the
definition of
aclass changes, each existing instance of the class is updated to
the new
format the next time it is accessed.
Each slot-spec is one of:
slot-name a non-null symbol.
(slot-name initial-value-form)
(slot-name slot-option...)
Each slot-option is an option name followed by its value.
The defined slot-options and their arguments are:
= initial-value-form
This an alternate way for providing a default initial
value form.
How is this form distinguished from the previous. By having more than
two elements??? How do you not give an init value form.
:accessor generic-function-name
Specifies that a function named
generic-function-name
be automatically generated, to read the value of
this
slot. SETF may be used with generic-function name
to
write the value of the slot.
OK. If generic-function-name is NIL then this is a NOOP. Specified so
programs can generate these.
:reader generic-function-name
Specifies that a function named
generic-function-name
be automatically generated, to read the value of
this
slot.
We have called this :read-accessor. We specify that if this is given,
then SETF may NOT be used with this accessor. If generic-function-name
is NIL then this is a NOOP.
:initable keyword
Specifies a keyword to be used to specify an
initial
value of this slot, when a new instance is being
made.
I think this is OK. Should allow value of NIL. Default is T
:allocation
:allocation can have values
:instance (allocated in the instance),
:class (storage allocated in the class and shared by all instances),
:dynamic (storage allocated in the instance on first use
(like Flavors Proplist mixin)
:none expect accessor methods for this to be defined for this slot
in this class
:initialize-only flag
If flag = T, then this slot cannot be changed after initialization (a
better name for :read-only). flag=T implies no accessors are generated.
default is NIL.
If no initial value is specified either in the DEFCLASS or the MAKE
form,
the initial value of the slot is undefined and it is an error to
reference
it. This is the same behavior as a DEFVAR with no
initial-value-form.
We hate these "it is an error" statements. We haven't discussed this
particular issue.
Each super-class-name is a non-null symbol.
Each option is one of:
option-name
(option-name argument...)
Each option-name is a keyword that names an option; the arguments
depend
on
the option.
OK
The set of defined options and their arguments is:
(:accessor-prefix prefix slot-name...)
(:reader-prefix prefix slot-name...)
(:default-init-plist keyword-argument...)
(:initable-slots slot-name...)
(:init-keywords keyword...)
The only one of these that we have agreed to is:
(:accessors-with-prefix string-or-symbol)
which causes accessors to be generated with the given prefix for ALL
slots that do not have local specification of any of :accessor,
:read-accessor, or :initialize-only. If this form does not appear, then
no accessors for slots are generated.
Note they we have made this be a single default that applies uniformly.
No specific slots can be mentioned, and this option can appear only
once. The arguments for this way of doing business are:
1) Anything not uniform is local to a slot description
2) There are no redundant, possibly inconsistent, declarations
(:documentation string)
OK
(:meta-class class-name)
No, we think this should be done using the meta-object protocol, since
the parsing of the defclass is not under the control of the meta-class.
However, I think we could be convinced otherwise.
(:required-classes class-name...)
(:required-init-keywords keyword...)
(:required-slots slot-name...)
(:required-methods generic-function-name...)
No. These seem like environmental features, and should not be part of
the spec. We should make some comment about how additional options may
be supported by the standard class in particular implementations, and
ones not understood will either be ignored, or have warnings issued.
(:constructor function-name lambda-list)
We have allowed the full generality of the defstruct syntax for this
one. Do you think it should be restricted to this boa-constructor
For the :ACCESSOR-PREFIX, :READER-PREFIX, and :INITABLE-SLOTS
options,
you can omit slot-names to indicate that the option applies for all
slots of
this class.
See above
It is legal to specify more than one accessor and reader for a
single
slot.
We argued about this, and decided we didn't like it. Why is it good?
DEFINING METHODS AND SETF METHODS
The general syntax for defining a method is:
(DEFMETHOD generic-function-name method-option...
method-lambda-list
body...)
No. See my earlier message.
(DEFMETHOD name-and-options
method-lambda-list
body...)
generic-function-name is a non-null symbol.
name-and-options is a non-null symbol or (name . method-options)
See my earlier message.
Each method-option is a non-null atom that describes the type of
this
method. Some examples of method-options are: :BEFORE and :AFTER.
method-lambda-list is a lambda-list with one difference. Where a
lambda-list allows only a variable and not a list, a
type-qualified-
variable may be used. However, type-qualified-variables cannot be
used
for
&aux variables, supplied-p parameters, or &rest parameters. A
type-qualified-variable is a list such as: (variable-name
type-specifier).
Note that the use of &optional is still under discussion.
type-specifier ---tbd---
type-specifer and its uses should be replaced by argument-specifier.
This will include class-names (class-specifiers) and individuals. The
meaning of argument-specifier may be extended by users who build their
own discriminators.
For convenience in defining a classical method, the following
syntax is
provided:
(DEFMETHOD (generic-function-name first-arg-type method-option...)
method-lambda-list
body...)
The classical syntax is equivalent to the following expression in
the
general syntax:
(DEFMETHOD generic-function-name method-option...
((self first-type-arg) method-lambda-list...)
(with (self)
body...))
See other message
The general syntax for defining a SETF method is:
(DEFMETHOD-SETF generic-function-name method-option...
method-lambda-list setf-lambda-list
body...)
The classical syntax for defining a SETF method is:
(DEFMETHOD-SETF (generic-function-name first-arg-type
method-option...)
method-lambda-list setf-lambda-list
body...)
generic-function-name and method-option are the same as for
DEFMETHOD.
setf-lambda-list is a lambda-list containing exactly one required
parameter, which may be type-qualified. In other words,
setf-lambda-list
is one of:
(variable-name)
((variable-name type-specifier))
Same problem with this syntax. But we agree that DEFMETHOD-SETF is a
better name. If you liked my other syntax suggestions, then this one
follows. Again type-specifier -> argument-specifier. Are we not
allowing multiple values to be stored. In the silver book it talks
about extensions to the corresponding list of store variables. I have
no problem with the restriction.
DEFINING GENERIC FUNCTIONS
(DEFGENERIC generic-function-name lambda-list option...)
(DEFGENERIC-SETF generic-function-name lambda-list setf-lambda-list
option.
generic-function-name is a non-null symbol.
lambda-list is an ordinary lambda-list except no &aux variables are
allowed.
setf-lambda-list is (variable-name).
Yes, except that we allow a documentation string before the options.
What do you think???
Each option is one of:
option-name
(option-name argument...)
Each option-name is a keyword that names an option; the arguments
depend
on the option.
OK
The set of defined options and their arguments is:
[--Should declarations and doc strings be allowed?--]
(:documentation string)
See above.
(:optimize spec...)
Is this for all methods, or just the discriminating function. This seems
weird to me
(:method-combination name argument...)
What is the argument in this form?
(:generic-function-class class-name)
(:method-class class-name)
(:order parameter-name...)
We have been using :dispatch-order for the keyword :order. It should
really be
:argument-precedence-order.
[more?]
Additional options should be allowed, as in defclass.
WITH
We have agreed that WITH should exist, but we haven't decided
anything
more specific about it yet.
Right; we haven't decided anything yet. There are two different
proposals under discussion. One turns names in calls on the accessors
(we call that one WITH). The other turns them into primitive slot
accesses (we call that one %WITH).
DEFINING NEW TYPES OF METHOD COMBINATION
(DEFINE-SIMPLE-METHOD-COMBINATION name operator-name
[single-arg-is-value]
[pretty-name])
This function defines a new type of method combination in which all
the
methods are called and their values are passed to the operator
specified
by
operator-name.
name is a non-null symbol, often a keyword, that is the name of the
type
of method combination being defined.
operator-name can be a symbol or a lambda-expression,
the name of a function, a macro, or a special form.
single-arg-is-value is t or nil; by default it is nil.
pretty-name is a string. It defaults to the lower case version of
the
supplied name.
We haven't agreed to this at all yet. super-daemon method combination
we believe in. But this simple case seems strange to me, and if it can
be defined with the stronger DEFINE-METHOD-COMBINATION, then let's not
put it in the spec.
I didn't see whoppers described in daemon combination section of the
Flavors manual -- at least not in the early section. Does this mean
that it is not a feature of daemon combination?
We believe that at least on the west coast, run-super will be used much
more than daemon combination. Hence my attempt to unify them. An
answer to Moons answer next week.
(DEFINE-METHOD-COMBINATION method-combination-type-name
lambda-list
(method-pattern...) option... body...)
This function behaves the same way as in Flavors. See the Flavors
documentation for details.
We believe that a simple version of this should be in the spec. I don't
know yet what simple means. At least powerful enough to define the
extended features, but not including the full library of standardly
available combinations types.
Making a New Instance
(MAKE class-name keyword-argument...)
MAKE is the function that makes and initializes an instance of a
class.
The allowed keyword-arguments depend on the DEFCLASS form. Any
keyword
specified with the :INITABLE, :INITABLE-SLOTS, or :INIT-KEYWORDS
option
is allowed.
If a keyword-argument is given to MAKE, it overrides any default
that is
given in the DEFCLASS form, such as the :DEFAULT-INIT-PLIST option,
or
the initial-value-form syntax.
Modulo isssues on keywords and specification of initable, this is
basically correct.
OTHER FUNCTIONS
Other functions of interest to the general programmer [---tbd---].
This list came from the 8 August meeting; it can serve as a
starting
agenda
for this section:
find-flavor / class-named
Yes class-named
typep
classp is the right name
type-of
class-of
Yes on class-of
operation-handled-p ??
Something like this is needed
remove-class
remove-method
change-class
Yes
-- danny
∂05-Sep-86 1955 Owners-CommonLoopsCore↑.PA@Xerox.COM Methods Selected by Predications More General Than Classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Sep 86 19:55:26 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 05 SEP 86 19:53:35 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA@XEROX.ARPA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 05 SEP 86 19:53:11 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 75331;
Fri 5-Sep-86 22:52:05 EDT
Date: Fri, 5 Sep 86 22:52 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Methods Selected by Predications More General Than Classes
To: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860905225205.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
The following message appears to have been lost in the network.
At least, it's not in the archive, and Danny's messages indicate
that he obviously hasn't read it. Maybe what really happened is
that I forgot to send it, but just edited it into my own file.
In any case, here it is.
CommonLoops allows method selection by classes and by one kind of
predication, equality to a constant (EQL, I presume). If we're going to
go more general than classes, we should allow the full generality of
Common Lisp types, i.e. arbitrary predications. The problem with that
is that there can be predications that have objects in common, but do
not have a subtype/supertype relationship. Thus if methods are defined
for both predications, it is not clear which method has precedence.
I think the answer is that actually encountering such a method ambiguity
signals an error, but that should not stop you from defining a method on
one predication, only from defining methods on two overlapping
predications. Note that by shadowing the ambiguous method pair with a
method on a more specific class you can prevent the error from being
signalled (I say a more specific class rather than a more specific
predication because the specificness of course has to be computable--see
below).
I strongly believe that it would be a mistake for the type specifiers
in methods to be a whole different type system from the regular Common
Lisp type system. Methods should either allow their arguments to be
qualified with any Common Lisp type specifier, or should restrict the
allowable type specifiers to a certain subset, but there absolutely
should not be extensions to the Common Lisp type system that only work
in method argument lists. That would be too confusing. This means that
the way CommonLoops does methods on individuals now is out. If we're
going to include methods on individuals in the standard, they have to
be done with MEMBER, not with QUOTE. I believe that in fact methods
on arbitrary predications can be implemented, allowing the whole Common
Lisp type system to be supported, and the remainder of this message
is a sketch of one way to implement that.
Any predication can be converted to the canonical form
(OR (AND class1 test1)
(AND class2 test2)...)
where each test is any Common Lisp type expression, and the classes are
all distinct. Any Common Lisp type expression specifies a set of
objects that all belong to some class, even if it's T, along with a
restriction to a subset of the total membership of that class. OR is
introduced essentially as a performance optimization for method
dispatching, to cut down the frequency of resorting to T as the class
for Common Lisp's OR type specifiers. Some kind of rule is required to
decide between minimizing the number of terms in the OR and using the
least general classes. It would also be convenient, but not essential,
to have rules for canonical ordering of the OR terms and canonical
formation of the test type expressions. Some examples:
class-name = (OR (AND class-name T))
(UNSIGNED-BYTE 8) = (OR (AND FIXNUM (INTEGER 0 255)))
;assuming FIXNUM is a class on its own, rather than just having INTEGER
(NOT FLOAT) = (OR (AND T (NOT FLOAT)))
Any two predications can be compared. In fact SUBTYPEP could be used,
but it's easier to think about in terms of the canonical form. I could
write down the rules for how to compare canonical forms in terms of
class precedence and SUBTYPEP on the tests. The result can be a
definite ordering of the predications <, =, >, or disjoint; the latter
means that it is definitely known that no object can satisfy both
predications. The result can also be that the ordering is uncomputable;
this happens when the same class has two different tests and the
ordering of the tests is uncomputable, e.g. SATISFIES of two different
functions. When the ordering is uncomputable, all this means is that
less optimization of the discriminating function is possible; at run time
both predications must be evaluated, and if both are true an error must
be signalled. The discriminating function would exploit the class portion
of the canonical form to avoid evaluating predications when it can prove
from the class that they must be false.
Aside: I don't know whether it's in general safe to trust every
implementation's SUBTYPEP function to work. It would be a pity if the
portable OOP system had to duplicate that functionality.
Aside: I believe the type COMMON is a predication, not a class.
I think so not only because it's so ill-defined, but also because
I can see how you might conceivably define methods on COMMON but
I don't see the point to having a class inherit from COMMON.
As for NULL and VECTOR, we get to decide whether these types are classes
or predications. I think it's clear that VECTOR should be a class,
and we just have to choose some precedence order of ARRAY and SEQUENCE.
The advantage of making NULL a predication rather than a class is that
method clashes between the SYMBOL and LIST classes are guaranteed to
signal an error, instead of using whichever non-obvious precedence order
we happened to choose.
∂08-Sep-86 1458 RPG Re: Defmethod syntax proposal
∂08-Sep-86 0945 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Defmethod syntax proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Sep 86 09:45:22 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 08 SEP 86 09:12:45 PDT
Redistributed: CommonLoopsCore↑.PA
Received: from Cabernet.ms by ArpaGateway.ms ; 08 SEP 86 09:11:09 PDT
Date: 8 Sep 86 09:10 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: Defmethod syntax proposal
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 5 Sep 86 20:51 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860908-091245-2678@Xerox>
In thinking about it over the weekend, I realized that the syntax we proposed
(defmethod name-or-name-and-options lambda-list ...)
where name-or-name-and-options = name|
(name {combine-options}*)|
(name class-name {combine-options}*)
is completely unambiguous whether one is using "classical" syntax and general syntax.
In "classical" syntax, no argument of lambda-list can be type specified.
In general syntax at least one must be specifed if you are using
method combination options.
<classical-method-def>:=(demethod (generic-name type .{combine-options}*)
unqualified-lambda-list body)
<general-method-def>:=(defmethod name qual-or-unqualified-lambda-list body)|
(defmethod (name . {combine-options}*) qualified-lambda-list body)
I do not like having two syntax's as part of the standard. The difference
in typing is only four characters (self) and the general syntax makes it clear what
variable is being used. With compatibility assured, certain implementations
could support the "classical" syntax as a convenience
or a backwards compatibility feature.
In this case I guess I take a minimimalist position.
-- danny
∂08-Sep-86 1500 RPG Re: Defmethod syntax proposal
∂08-Sep-86 1043 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Defmethod syntax proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Sep 86 10:42:47 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 08 SEP 86 10:02:36 PDT
Return-Path: <Moon@YUKON.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA@XEROX.ARPA
Received: from YUKON.SCRC.Symbolics.COM (SCRC-YUKON.ARPA) by Xerox.COM ;
08 SEP 86 10:00:04 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by YUKON.SCRC.Symbolics.COM
via CHAOS with CHAOS-MAIL id 81811; Mon 8-Sep-86 12:57:58 EDT
Date: Mon, 8 Sep 86 12:58 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Defmethod syntax proposal
To: CommonLoopsCore↑.PA@Xerox.COM
In-Reply-To: <860908-091245-2678@Xerox>
Message-ID: <860908125848.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 8 Sep 86 09:10 PDT
From: Bobrow.pa@Xerox.COM
In thinking about it over the weekend, I realized that the syntax we proposed
(defmethod name-or-name-and-options lambda-list ...)
where name-or-name-and-options = name|
(name {combine-options}*)|
(name class-name {combine-options}*)
is completely unambiguous whether one is using "classical" syntax and general syntax.
In "classical" syntax, no argument of lambda-list can be type specified.
In general syntax at least one must be specifed if you are using
method combination options.
<classical-method-def>:=(demethod (generic-name type .{combine-options}*)
unqualified-lambda-list body)
<general-method-def>:=(defmethod name qual-or-unqualified-lambda-list body)|
(defmethod (name . {combine-options}*) qualified-lambda-list body)
That was my original proposal, which foundered on the CommonLoops "default
method" feature, which allows defining a "general" method with no type
specifiers. I don't see why method combination options would be
disallowed for default methods. If it doesn't make sense to allow such
options for default methods, then we can go back to that proposal. I'd be
willing to give up the feature of type qualifying additional arguments
while still using classical syntax, for the sake of agreement.
I do not like having two syntax's as part of the standard. The difference
in typing is only four characters (self) and the general syntax makes it clear what
variable is being used.
No, the important difference is that in the classical syntax you don't have to
say "with" explicitly.
With compatibility assured, certain implementations
could support the "classical" syntax as a convenience
or a backwards compatibility feature.
In this case I guess I take a minimimalist position.
I wasn't able to figure out what this means.
∂08-Sep-86 1500 RPG Class versus Type System
∂08-Sep-86 1043 Owners-commonloopscore↑.pa@Xerox.COM Class versus Type System
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Sep 86 10:43:08 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 08 SEP 86 10:26:33 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 08 SEP 86
10:26:19 PDT
Date: 08 Sep 86 10:25 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: Class versus Type System
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860908-102633-2759@Xerox>
For those who have problems with English, I'll rephrase my remark
and add a few more.
Rephrased remark:
We, the people who are designing the new specification of the Common Lisp
Object System, must take into consideration the fact that, as it currently
stands, there is a distinction between the Common Lisp type system and the
proposed Common Lisp Object System class system. In order for us to keep
our own terminology straight, I have proposed the term `argument
specifier,' which, loosely speaking, is equivalent to the term `type
specifier' that Moon uses.
Further remarks:
(1) I believe that the Common Lisp type, COMMON, is well-defined. However,
it is possible that people do not have a good model of what it comprises;
also it is possible that COMMON would not be a particularly useful class
within the context of the Common Lisp Object System class system.
(2) Extending the Common Lisp Object System class system to include the
sorts of type predications that the Common Lisp type system admits strikes
me as misguided. First, considering implemenations, SUBTYPEP does not, I
believe, behave uniformly over all Common Lisp implementations; that is, I
believe, although I have no examples at hand, that are two Common Lisp
implementations and two type specifiers, S1 and S2, such that one
implementation returns the values NIL NIL when it evaluates the expression
(subtypep s1 s2) whereas the second implementation returns NIL T when it
evaluates the same expression: it is possible that worse discrepancies
exist. Second, considering implementation technology, the Common Lisp
implementations that supply a SUBTYPEP that behaves in such a way that
most observers would conclude that those Common Lisp systems supply a
SUBTYPEP that produces the most consistently accurate results over a set
of test cases for SUBTYPEP, where the observers are considering most of
the available Common Lisp systems, are Common Lisp systems in which the
implementation of SUBTYPEP is more inefficient than those that are judged
to be less accurate. The implication of this observation is that generic
function invocation is likely to be an expensive operation if SUBTYPEP is
used as part of the basic method selection implementation. The
implication of the first observation is that it is likely that it will be
required of the implementors of the basic method selection functions to
use a common implementation (at some level of abstraction), or else the
behavior of the basic method selection functions will need to be specified
in great detail. My third remark is based on hearsay: I know three
mathematicians who regard the Common Lisp type system and SUBTYPEP
in particular with extreme disdain. If any reader of this wishes, I will
interview these individuals to learn their reasons for disdain and
report those reasons.
-rpg-
∂08-Sep-86 1529 RPG Re: Methods Selected by Predications More General Than Classes
∂08-Sep-86 1147 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Methods Selected by Predications More General Than Classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Sep 86 11:47:04 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 08 SEP 86 10:51:10 PDT
Redistributed: CommonLoopsCore↑.PA
Received: from Cabernet.ms by ArpaGateway.ms ; 08 SEP 86 10:50:46 PDT
Date: 8 Sep 86 10:50 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: Methods Selected by Predications More General Than Classes
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 5 Sep 86 22:52 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860908-105110-2796@Xerox>
The following message (about arg specification) appears to have
been lost in the network...
I had not seen it.
I strongly believe that it would be a mistake for the type specifiers in
methods to be a whole different type system from the regular Common Lisp
type system. Methods should either allow their arguments to be qualified
with any Common Lisp type specifier, or should restrict the allowable type
specifiers to a certain subset, but there absolutely should not be
extensions to the Common Lisp type system that only work in method
argument lists. That would be too confusing.
I disagree. I think the set of specifiers for methods need not overlap
the Common Lisp type system. Therefore I do not feel at all
uncomfortable with having a different set of specifications based on
classes and individuals.
HOWEVER, after rereading Moon's message, I felt that he has proposed a
reasonable extension to the current specification mechanism. Subtypep
must be extended to include
(subtypep class-name1 class-name2)
if (subclassp (class-named class-name1) (class-named class-name2))
I would want to extend the type system to deal with
(QUOTE inst) as a short hand for
(SATISFIES (MEMBER '(inst))
since individuals are so useful in type specification.
This imlies the following which is peculiar but OK.
(typep x ''inst) = (eql x 'inst)
We can think of methods for a generic function as specifying a (nested)
set of guarded clauses. The nesting is determined by subtypep
relationships.
I think we must trust every implementations subtypep, despite Moon's
worry. Having two different but similar features in the language is
exactly what we are trying to avoid extending the argument specification
to the full type system.
Since the implementation for classes and individuals as specifiers will
clearly be both the most efficient, and most useful, we might postpone
the description of this to the advanced chapter.
Moon's OR hack should be in implementation notes.
-- danny
∂08-Sep-86 1533 RPG Class versus Type System
∂08-Sep-86 1147 Owners-commonloopscore↑.pa@Xerox.COM Class versus Type System
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Sep 86 11:47:42 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 08 SEP 86 11:39:07 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.pa@XEROX.ARPA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 08 SEP 86 11:38:43 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 76448;
Mon 8-Sep-86 14:13:18 EDT
Date: Mon, 8 Sep 86 14:13 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Class versus Type System
To: commonloopscore↑.pa@Xerox.COM
In-Reply-To: <860908-102633-2759@Xerox>
Message-ID: <860908141318.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 08 Sep 86 10:25 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
....The implication of this observation is that generic
function invocation is likely to be an expensive operation if SUBTYPEP is
used as part of the basic method selection implementation.
Since method selection operates (conceptually; I'm not talking about
implementations, which no doubt will all use techniques that are more
optimal than this, but provide the same semantics) by doing a series
of TYPEP tests where the first argument is an argument to the generic
function and the second argument is a type specifier from the lambda list
of a method, I fail to see how the expense of SUBTYPEP could affect the
expense of generic function invocation, since even conceptually SUBTYPEP
is not called during generic function invocation.
The thing SUBTYPEP is useful for is deciding in what order to do those
TYPEP tests. This happens when constructing the discriminator, not
every time a generic function is invoked.
It's all the same to me if we decide that for practical or other reasons
we don't want to generalize to allow arbitrary Common Lisp type
specifiers to qualify method arguments, but instead decide to limit
these to some subset, even as small a subset as just class names. Even
though I think it's quite clear how to do the full generalization, I am
always opposed to premature standardization on ideas that have not been
tested in the field. As I've said before, the one thing we must not do
is to develop yet another type system that is not just a subset of the
regular type system.
....The
implication of the first observation is that it is likely that it will be
required of the implementors of the basic method selection functions to
use a common implementation (at some level of abstraction), or else the
behavior of the basic method selection functions will need to be specified
in great detail.
Surely it will be a disaster if the specification of this standard is so poor
that users can't figure out what it specifies, except by experimenting with
a particular implementation that is said to implement the standard. I hope I
misunderstood you.
∂08-Sep-86 1535 RPG Generic Functions Defined by Defmethod
∂08-Sep-86 1245 Owners-commonloopscore↑.pa@Xerox.COM Generic Functions Defined by Defmethod
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Sep 86 12:45:05 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 08 SEP 86 11:54:23 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 08 SEP 86
11:53:50 PDT
Date: 08 Sep 86 10:53 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: Generic Functions Defined by Defmethod
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860908-115423-2902@Xerox>
My comments regarding the situation in which DEFMETHOD creates
a generic function in case there is not already one is based on
my belief of the model that users will develop for generic functions
rather than on implementation considerations, which considerations Moon
believes that I have in mind when I make such remarks.
Let me be more precise. Consider the combination
(defmethod gf ...)
and let us suppose that there is no generic function already
associated with the name, `gf.' Should the defmethod expression
above create a generic function and associate it with the name,
`gf'? My belief of the model that most users of the Common Lisp
Object System will develop is that of a generic function being an
object, some of whose parts comprise the methods defined or specified
by the various defmethod forms which are evaluated and which
specify the same name with which the generic function in question
is associated. Given the belief that generic functions are primary,
will users be confused by the fact that defmethod, a special form
or macro that is used to define a subpart of an object, creates the
object of which it is a subpart if the object does not already exist?
I believe that they will be confused.
There are two techniques we can use to define defmethod in such a
way that defmethod will create the generic function in case it does
not already exist:
(1). we can define a generic function as an abstract data type
whose signature (the operations that can be used on instances
of the abstract data type) includes defmethod along with the
functionality of creating generic functions.
One possible concern with this approach is that the signature
requires possibly confusing-to-the-user behavior from such
functions as SYMBOL-FUNCTION. I have not explored this behavior
in detail.
(2). we can state that when the Common Lisp Object System is loaded,
every symbol has (or can be considered to have) a generic function
associated with it such that this default generic function has no
methods associated with it and such that the other properties of
the generic function have such default values as we may define.
In this way, DEFMETHOD can be crisply defined to operate on
the subparts of a generic function while still retaining
the functionality Bobrow desires.
I apologize to Moon for the fact that my explanation of my belief of the
model that users will develop for generic functions included an analogy
which was presented using a piece of code, which presentation in terms of
code apparently caused him to believe that my concern was for the
implementation details of generic functions rather than for the user model
of the situation.
-rpg-
∂08-Sep-86 1537 RPG Re: Defmethod syntax proposal
∂08-Sep-86 1413 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Defmethod syntax proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Sep 86 14:13:15 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 08 SEP 86 13:13:17 PDT
Redistributed: CommonLoopsCore↑.PA
Received: from Cabernet.ms by ArpaGateway.ms ; 08 SEP 86 13:13:06 PDT
Date: 8 Sep 86 13:13 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: Defmethod syntax proposal
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 8 Sep 86 12:58 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860908-131317-2999@Xerox>
I don't see why method combination options would be disallowed for
default methods. If it doesn't make sense to allow such options
for default methods, then we can go back to that proposal.
I think of defmeth with no argument specification as basically a defun
followed by a make-specializable. If one wants to provide combination
for all methods, than a class specifier of T would allow use of method
combination with full scope.
No, the important difference is that in the classical syntax you
don't
have to say "with" explicitly.
I think it might be a good idea to provide a simple syntax for WITH in
the type specification; for example, ((X class-foo :with-vars) in the
arglist.
With compatibility assured, certain implementations
could support the "classical" syntax as a convenience
or a backwards compatibility feature.
In this case I guess I take a minimimalist position.
I wasn't able to figure out what this means.
I meant that I propose that we not describe classical syntax as part of
the standard. It would simply be a backwards compatibility feature for
Flavors users.
-- danny
∂08-Sep-86 1654 RPG Re: Defmethod syntax proposal
∂08-Sep-86 1614 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Defmethod syntax proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Sep 86 16:10:29 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 08 SEP 86 15:50:27 PDT
Return-Path: <DLW@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA@XEROX.ARPA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 08 SEP 86 15:50:12 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 76801;
Mon 8-Sep-86 18:39:41 EDT
Date: Mon, 8 Sep 86 18:41 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Re: Defmethod syntax proposal
To: Bobrow.pa@Xerox.COM
cc: CommonLoopsCore↑.PA@Xerox.COM
In-Reply-To: <860908-131317-2999@Xerox>
Message-ID: <860908184131.4.DLW@CHICOPEE.SCRC.Symbolics.COM>
Date: 8 Sep 86 13:13 PDT
From: Bobrow.pa@Xerox.COM
I meant that I propose that we not describe classical syntax as part of
the standard. It would simply be a backwards compatibility feature for
Flavors users.
It's really more than that; it provides conceptual compatibility for
people who are familiar with most any of the other existing
object-oriented programming languages, particularly Smalltalk-80.
It provides the familiar concepts of instance variables and "self".
Because of the widespread establishment of these concepts, I think
it's worth putting this into the standard for everyone, despite the
minor inelegance of having two syntaxes when only one is logically
necessary.
∂08-Sep-86 1654 RPG Generic Functions Defined by Defmethod
∂08-Sep-86 1614 Owners-commonloopscore↑.pa@Xerox.COM Generic Functions Defined by Defmethod
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Sep 86 16:10:22 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 08 SEP 86 15:29:40 PDT
Return-Path: <DLW@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.pa@XEROX.ARPA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 08 SEP 86 15:29:22 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 76792;
Mon 8-Sep-86 18:28:03 EDT
Date: Mon, 8 Sep 86 18:29 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Generic Functions Defined by Defmethod
To: RPG@SAIL.STANFORD.EDU, commonloopscore↑.pa@Xerox.COM
In-Reply-To: <860908-115423-2902@Xerox>
Message-ID: <860908182948.3.DLW@CHICOPEE.SCRC.Symbolics.COM>
I understand the point you're making. As I've said, I'm undecided on
this issue personally, but since I believe I understand the other side
of the argument, I'll speak for it. I think the answer to your point is
as follows:
The analogy you presented with cons cells, is, as you said, extreme.
The opposite extreme analogy might be to insist that, in Lisp, one
explicitly create each symbol before using it, by calling intern on a
string, or something. After all, the appearance of a symbol means that
it should be looked up in a table; isn't it confusing that sometimes it
should create a symbol rather than looking one up?
Or, to abandon extreme analogies and speak more plainly, the proposed
conceptual model for why defmethod should create a generic function is
that "it's like intern"; the first mention causes an automatic creation,
to save you the trouble of doing one manually.
∂08-Sep-86 1727 RPG Re: Defmethod syntax proposal
∂08-Sep-86 1705 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Defmethod syntax proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Sep 86 17:05:04 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 08 SEP 86 16:13:56 PDT
Redistributed: CommonLoopsCore↑.PA
Received: from Cabernet.ms by ArpaGateway.ms ; 08 SEP 86 16:13:39 PDT
Date: 8 Sep 86 16:13 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: Defmethod syntax proposal
In-reply-to: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>'s
message of Mon, 8 Sep 86 18:41 EDT
To: DLW@ALDERAAN.SCRC.Symbolics.COM
cc: Bobrow.pa@Xerox.COM, CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860908-161356-3282@Xerox>
Date: 8 Sep 86 13:13 PDT
From: Bobrow.pa@Xerox.COM
I meant that I propose that we not describe classical syntax as
part
of the standard. It would simply be a backwards compatibility
feature
for Flavors users.
It's really more than that; it provides conceptual compatibility
for
people who are familiar with most any of the other existing
object-oriented programming languages, particularly Smalltalk-80.
It provides the familiar concepts of instance variables and "self".
Because of the widespread establishment of these concepts, I think
it's worth putting this into the standard for everyone, despite the
minor inelegance of having two syntaxes when only one is logically
necessary.
(defmethod foo ((self class-name) ...) provides self as a cliche, and
allows those users the optioning of providing a more mnemonic name for
self. Instance variables (or slots as we are calling them) are
available in either case. Using the general syntax also encourages
users to remmber that this is a generic function and others may define
extensions (new defmethods) that specialize more than one argument. I
think that separate syntax will cause mind bugs of the sort -- 'well I
did a "classical" defmethod so now I can't specialize other args.'
-- danny
∂08-Sep-86 1728 RPG Class versus Type System
∂08-Sep-86 1707 Owners-commonloopscore↑.pa@Xerox.COM Class versus Type System
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Sep 86 17:05:20 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 08 SEP 86 16:21:02 PDT
Return-Path: <DLW@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.pa@XEROX.ARPA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 08 SEP 86 16:20:48 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 76812;
Mon 8-Sep-86 19:19:38 EDT
Date: Mon, 8 Sep 86 19:21 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Class versus Type System
To: Moon@STONY-BROOK.SCRC.Symbolics.COM, commonloopscore↑.pa@Xerox.COM
In-Reply-To: <860908141318.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <860908192128.5.DLW@CHICOPEE.SCRC.Symbolics.COM>
Date: Mon, 8 Sep 86 14:13 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Surely it will be a disaster if the specification of this standard is so poor
that users can't figure out what it specifies, except by experimenting with
a particular implementation that is said to implement the standard. I hope I
misunderstood you.
Well, I think RPG is probably right about SUBTYPEP being inconsistent
from one implementation to the next. As I see it, SUBTYPEP is answering
the following question: "Is it the case that for all objects X, such
that X is of type T1, it is necessarily true that X is of type T2"? The
problem is that there are two interpretations of this question. One
interpretation asks "... for all objects X where X is any object that
can exist in this particular superset of Common Lisp ...", and the other
interpretation asks "... for all objects X where X is any object that
can exist in every Lisp that is a subset of Common Lisp ...". If two
implementations both use the first interpretation, it's easy to see how
they might be inconsistent.
I think that specific cases of this problem have been discussed on
Common-Lisp, but I don't remember the details. I could be wrong about
this. They have to do with areas in which the implementor is given
latitude, such as the decision of how to implement instances of
defstructs and things like that. An easy example might be
(subtypep 'single-float 'short-float)
in an implementation in which they are the same thing. This
form returns T T in our implementation.
∂09-Sep-86 2035 RPG Re: Subtypep
∂09-Sep-86 1947 Bobrow.pa@Xerox.COM Re: Subtypep
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Sep 86 19:47:18 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 SEP 86 17:52:00 PDT
Date: 9 Sep 86 17:46 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: Subtypep
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 08 Sep 86
17:35 PDT
To: RPG@SAIL.STANFORD.EDU
cc: commonloopscore↑.pa@Xerox.COM
Message-ID: <860909-175200-1153@Xerox>
CLASS-OF will be as poorly defined as the current TYPE-OF.
Why is this ill-defined? It is not TYPE-OF. It returns the most
specific class for the instance.
-- danny
∂09-Sep-86 2244 RPG Re: Summary of features we all agree on
∂09-Sep-86 2158 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Summary of features we all agree on
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Sep 86 21:58:11 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 09 SEP 86 21:41:34 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA@XEROX.ARPA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 09 SEP 86 21:40:45 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 99736; Wed
10-Sep-86 00:39:48 EDT
Date: Wed, 10 Sep 86 00:39 EDT
From: David A. Moon <Moon@SCRC-STONY-BROOK.ARPA>
Subject: Re: Summary of features we all agree on
To: CommonLoopsCore↑.PA@Xerox.COM
In-Reply-To: <860905-184912-1633@Xerox>
Message-ID: <860910003916.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 5 Sep 86 18:49 PDT
From: Bobrow.pa@Xerox.COM
(DEFCLASS class-name (slot-spec...) (super-class-name...)
option...)
Not quite. We have the opposite order for (super-class-name...)
and (slot-spec...).
(DEFCLASS class-name (super-class-name...) (slot-spec...)
option...)
We can probably go along with this, but it ought to be
discussed. What was the motivation for changing the order?
class-name is a non-null symbol that names the class being
defined. If a class is already defined with this name, this
definition replaces the old definition. The default
meta-class ensures that when the definition of a class
changes, each existing instance of the class is updated to the
new format the next time it is accessed.
Each slot-spec is one of:
slot-name a non-null symbol.
(slot-name initial-value-form)
(slot-name slot-option...)
Each slot-option is an option name followed by its value.
The defined slot-options and their arguments are:
= initial-value-form
This an alternate way for providing a default
initial value form.
How is this form distinguished from the previous. By having more than
two elements???
Yes. (slot-name initial-value-form) is a convenient
abbreviation for (slot-name = initial-value-form).
How do you not give an init value form.
The way you omit the initial value form when giving slot-options
is to omit the = slot-option. I thought this was discussed in
the mail a while back but I could be misremembering.
By the way I'm not wedded to the name "=". I couldn't think of
a clearer name when I tried for a few minutes, but perhaps
someone else can.
:accessor generic-function-name
Specifies that a function named generic-function-name
be automatically generated, to read the value of this
slot. SETF may be used with generic-function name to
write the value of the slot.
OK. If generic-function-name is NIL then this is a NOOP.
Specified so programs can generate these.
:reader generic-function-name
Specifies that a function named generic-function-name
be automatically generated, to read the value of this
slot.
We have called this :read-accessor.
I think users would find the distinction between :read-accessor
and :accessor confusing. Perhaps we need some more opinions
here, it's a difficult judgement.
We specify that if this is
given, then SETF may NOT be used with this accessor. If
generic-function-name is NIL then this is a NOOP.
Agreed.
:initable keyword
Specifies a keyword to be used to specify an
initial value of this slot, when a new instance is
being made.
I think this is OK. Should allow value of NIL. Default is T
I don't think you meant it when you said "default is T", since
the argument is a keyword. If you meant that unless the
programmer specifies otherwise, all slots can be initialized by
MAKE with keywords chosen by default, I don't think that is good
data abstraction. I don't think slots should be visible from
outside of the module that owns a class unless the definer of
the class explicitly makes them visible. We can provide a
defclass option that makes it very easy to make all the slots
initializable, but the default should be that features like this
are turned off until the programmer turns them on. This is the
same argument as the one that made us all decide that slot
accessors are not created unless the programmer asks for them.
:allocation
:allocation can have values
:instance (allocated in the instance),
:class (storage allocated in the class and shared by all
instances),
:dynamic (storage allocated in the instance on first use
(like Flavors Proplist mixin)
:none expect accessor methods for this to be defined for
this slot in this class
We need to discuss which of these allocation options belong in
the standard. Maybe only a subset of them.
:initialize-only flag
If flag = T, then this slot cannot be changed after
initialization (a better name for :read-only). flag=T implies
no accessors are generated. default is NIL.
Do we really need this feature? Why not just leave out the
:accessor if we don't want people to be able to setf the slot?
If no initial value is specified either in the DEFCLASS or the
MAKE form, the initial value of the slot is undefined and it
is an error to reference it. This is the same behavior as a
DEFVAR with no initial-value-form.
We hate these "it is an error" statements. We haven't discussed
this particular issue.
I don't think the object-oriented programming standard should
try to be the error-handling standard, too! Let's just say that
referencing an uninitialized slot has the same error
characteristics as referencing an uninitialized special
variable, and leave it to the rest of the language to define
just what that is.
Each super-class-name is a non-null symbol.
Each option is one of:
option-name
(option-name argument...)
Each option-name is a keyword that names an option; the
arguments depend on the option.
OK
The set of defined options and their arguments is:
(:accessor-prefix prefix slot-name...)
(:reader-prefix prefix slot-name...)
(:default-init-plist keyword-argument...)
(:initable-slots slot-name...)
(:init-keywords keyword...)
The only one of these that we have agreed to is:
(:accessors-with-prefix string-or-symbol)
which causes accessors to be generated with the given prefix for
ALL slots that do not have local specification of any of
:accessor, :read-accessor, or :initialize-only. If this form
does not appear, then no accessors for slots are generated.
Note they we have made this be a single default that applies
uniformly. No specific slots can be mentioned, and this option
can appear only once. The arguments for this way of doing
business are:
1) Anything not uniform is local to a slot description
2) There are no redundant, possibly inconsistent,
declarations
:accessors-with-prefix is certainly nice and simple, but it is
not the same as the last thing that was discussed in the mail.
And the other options were listed because they appeared in
"things we basically agree on" in the minutes of that meeting we
had at MIT, so we need to keep discussing this until we converge.
(:documentation string)
OK
(:meta-class class-name)
No, we think this should be done using the meta-object protocol,
since the parsing of the defclass is not under the control of
the meta-class. However, I think we could be convinced
otherwise.
You're the meta-class experts, but I think the idea of this
option was supposed to be to control the class of the class that
gets instantiated, but not to affect anything about the parsing
of the defclass.
(:required-classes class-name...)
(:required-init-keywords keyword...)
(:required-slots slot-name...)
(:required-methods generic-function-name...)
No. These seem like environmental features, and should not be
part of the spec.
I think you're wrong here, for two reasons. One is that I don't
agree that these are environmental; I see them as a necessary
part of defining a class and its relationships with other
classes. We've found these options to be heavily used when
setting up complex families of classes.
The second reason is that these aren't just error-checking.
:required-slots and :required-classes can make additional slot
names available as variables inside a WITH. This is necessary
to be able to write methods for abstract classes, and especially
for mixins, when part of the inter-component-class interface
takes the form of slots.
If we disagree we need to keep discussing this.
We should make some comment about how
additional options may be supported by the standard class in
particular implementations, and ones not understood will either
be ignored, or have warnings issued.
I don't think having defclass options quietly ignored in some
implementations is going to enhance portability.
(:constructor function-name lambda-list)
We have allowed the full generality of the defstruct syntax for
this one. Do you think it should be restricted to this
boa-constructor
No, I agree. Specifically, the lambda-list should be optional,
and default to (&key ...) where the ... is filled in according
to the :initable and :initable-slots (or whatever those options
end up being called) in the obvious way.
For the :ACCESSOR-PREFIX, :READER-PREFIX, and :INITABLE-SLOTS
options, you can omit slot-names to indicate that the option
applies for all slots of this class.
See above
It is legal to specify more than one accessor and reader for a
single slot.
We argued about this, and decided we didn't like it. Why is it good?
I think I pointed out in an earlier piece of mail that you might
want to have both an accessor and a reader, where the accessor
is used inside of a module while the reader is a public
interface. The idea is that you can't change the contents of
the slot using the public interface. I don't know of
applications for two accessors or two readers, but I don't see
any advantage to adding a special error-check to disallow that.
Why is it bad?
DEFINING METHODS AND SETF METHODS
The general syntax for defining a method is:
(DEFMETHOD generic-function-name method-option...
method-lambda-list
body...)
No. See my earlier message.
At the time Sonya and I put together this list of things that
we thought had been agreed upon, we didn't know that there was
still disagreement on the syntax of defmethod, since we had not
heard from you. As it turns out defmethod isn't ready to be
included yet. We need to keep working on it until we converge.
...But we agree that DEFMETHOD-SETF
is a better name.... Are we not allowing multiple values to be
stored? In the silver book it talks about extensions to the
corresponding list of store variables. I have no problem with
the restriction.
The extension mentioned on CLtL p.103 hasn't been incorporated
into Common Lisp yet, so I don't think it should be allowed to
sneak in through the object-oriented programming extension.
We should leave syntactic space for it, though, so having the
store-variable in a separate lambda-list is good.
DEFINING GENERIC FUNCTIONS
(DEFGENERIC generic-function-name lambda-list option...)
(DEFGENERIC-SETF generic-function-name lambda-list
setf-lambda-list option.
generic-function-name is a non-null symbol.
lambda-list is an ordinary lambda-list except no &aux
variables are allowed.
setf-lambda-list is (variable-name).
Yes, except that we allow a documentation string before the
options. What do you think???
Flavors allows a "naked" documentation string also, but I'm not
sure that ought to be in the standard. It's a matter of whether
you think it's more important to have the options in a uniform
format or to have defgeneric syntax be more analogous to defun
syntax.
Each option is one of:
option-name
(option-name argument...)
Each option-name is a keyword that names an option; the
arguments depend on the option.
OK
The set of defined options and their arguments is:
[--Should declarations and doc strings be allowed?--]
(:documentation string)
See above.
(:optimize spec...)
Is this for all methods, or just the discriminating function.
This seems weird to me
The question seems weird to me. I guess the problem is caused
by us including only the syntax and not the semantics so as to
get something out quickly for discussion, which meant that we
completely failed to communicate what this was all about.
The idea of the :optimize option to defgeneric in Flavors is
that there are a variety of possible ways of doing
discrimination, and in order for the system to choose among them
intelligently the user should be able to express his needs. In
the Common Lisp objected-oriented programming facility I presume
it would be a method of the discriminator, rather than
"the system", that is guided by this option, but otherwise the
concept of the :optimize option seems to carry over directly and
does not seem to be at all specific to Flavors. I believe it's
more portable for the user's needs to be expressed in terms of
which quality (speed or space) is more important, rather than
directly specifying the exact technique to be used.
(:method-combination name argument...)
What is the argument in this form?
Optional arguments received by parameters in the
define-method-combination. See the Flavors documentation.
(:generic-function-class class-name)
(:method-class class-name)
(:order parameter-name...)
We have been using :dispatch-order for the keyword :order. It
should really be :argument-precedence-order.
:argument-precedence-order is the best name I've heard for this
yet.
[more?]
Additional options should be allowed, as in defclass.
WITH
We have agreed that WITH should exist, but we haven't decided
anything more specific about it yet.
Right; we haven't decided anything yet. There are two different
proposals under discussion. One turns names in calls on the
accessors (we call that one WITH). The other turns them into
primitive slot accesses (we call that one %WITH).
No proposal is "under discussion" if the people on the east coast
haven't seen it. Send them along and we'll be happy to discuss
them.
DEFINING NEW TYPES OF METHOD COMBINATION
(DEFINE-SIMPLE-METHOD-COMBINATION name operator-name
[single-arg-is-value]
[pretty-name])
This function defines a new type of method combination in
which all the methods are called and their values are passed
to the operator specified by operator-name.
name is a non-null symbol, often a keyword, that is the name
of the type of method combination being defined.
operator-name can be a symbol or a lambda-expression, the name
of a function, a macro, or a special form.
single-arg-is-value is t or nil; by default it is nil.
pretty-name is a string. It defaults to the lower case
version of the supplied name.
We haven't agreed to this at all yet. super-daemon method
combination we believe in. But this simple case seems strange to
me, and if it can be defined with the stronger
DEFINE-METHOD-COMBINATION, then let's not put it in the spec.
It's a convenient abbreviation for people who don't want to have
to understand the full define-method-combination to do something
simple. What are you going to tell the user whose program is
non-portable because you decided to leave this out?
I didn't see whoppers described in daemon combination section of
the Flavors manual -- at least not in the early section. Does
this mean that it is not a feature of daemon combination?
Whoppers are described in their own section. They are not a
feature of daemon combination or any other particular type of
combination.
We believe that at least on the west coast, run-super will be
used much more than daemon combination. Hence my attempt to
unify them. An answer to Moons answer next week.
(DEFINE-METHOD-COMBINATION method-combination-type-name
lambda-list
(method-pattern...)
option...
body...)
This function behaves the same way as in Flavors. See the
Flavors documentation for details.
We believe that a simple version of this should be in the spec.
I don't know yet what simple means. At least powerful enough to
define the extended features, but not including the full library
of standardly available combinations types.
Making a New Instance
(MAKE class-name keyword-argument...)
MAKE is the function that makes and initializes an instance of
a class. The allowed keyword-arguments depend on the DEFCLASS
form. Any keyword specified with the :INITABLE,
:INITABLE-SLOTS, or :INIT-KEYWORDS option is allowed.
If a keyword-argument is given to MAKE, it overrides any
default that is given in the DEFCLASS form, such as the
:DEFAULT-INIT-PLIST option, or the initial-value-form syntax.
Modulo isssues on keywords and specification of initable, this
is basically correct.
OTHER FUNCTIONS
Other functions of interest to the general programmer
[---tbd---].
This list came from the 8 August meeting; it can serve as a
starting agenda for this section:
find-flavor / class-named
Yes class-named
typep
classp is the right name
The name TYPEP is already specified by Common Lisp, we can't
change it to something else. The issue here is what is to be
changed in the documentation of typep when the object-oriented
programming extension is added to the Common Lisp specification.
type-of
class-of
Yes on class-of
operation-handled-p ??
Something like this is needed
remove-class
remove-method
change-class
Yes
If we can discuss and reach agreement upon the few points of
disagreement above, we should be able to send out a revised
version of "Summary of features we all agree on" in a couple
of days and then move on to deeper issues.
∂09-Sep-86 2244 RPG lack of word from the west coast
∂09-Sep-86 2158 Owners-CommonLoopsCore↑.PA@Xerox.COM lack of word from the west coast
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Sep 86 21:58:03 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 09 SEP 86 21:35:06 PDT
Return-Path: <Moon@ALDERAAN.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA@XEROX.ARPA
Received: from ALDERAAN.SCRC.Symbolics.COM ([192.10.41.109]) by
Xerox.COM ; 09 SEP 86 21:34:51 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 3422; Wed
10-Sep-86 00:33:50 EDT
Date: Wed, 10 Sep 86 00:33 EDT
From: David A. Moon <Moon@SCRC-STONY-BROOK.ARPA>
Subject: lack of word from the west coast
To: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860910003335.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
The draft document outlining what has been learned so far
in the Xerox/Lucid meetings, which you said you would send
by the end of last week, has not yet arrived. I think you
had better send it again.
∂09-Sep-86 2324 RPG Class-of Versus Type-of
∂09-Sep-86 2258 Owners-commonloopscore↑.pa@Xerox.COM Class-of Versus Type-of
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Sep 86 22:57:36 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 09 SEP 86 22:53:12 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 09 SEP 86
22:53:02 PDT
Date: 09 Sep 86 22:52 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: Class-of Versus Type-of
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860909-225312-1464@Xerox>
Danny asked what I meant when I said that class-of might be ill-defined
in some situation. The situation I thought I was discussing was
the one in which the Common Lisp type system is subsumed by the
class system, and class-of is possibly expected to return `the
most specific class' in the presence of type specifiers which correspond
to classes and in the presence of types/classes that do not exist in
every Common Lisp (like simple- objects). Class-of is perfectly
well-defined in the current proposal in which the Common Lisp standard
type specifiers (minus atom and common) have (builtin) classes.
(Danny, I'm referring to the current West Coast proposal).
-rpg-
∂09-Sep-86 2336 RPG Things on which we agree
∂09-Sep-86 2326 Owners-commonloopscore↑.pa@Xerox.COM Things on which we agree
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Sep 86 23:26:33 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 09 SEP 86 23:24:49 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 09 SEP 86
23:24:40 PDT
Date: 09 Sep 86 23:24 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: Things on which we agree
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860909-232449-1480@Xerox>
Some of the West Coast people prefer MAKE-INSTANCE to MAKE.
The motivation is to leave good names alone when reasonably
short, reasonably descriptive names are available.
********************************************************************
When I read something like:
:accessor generic-function-name
Specifies that a function named generic-function-name
be automatically generated, to read the value of this
slot. SETF may be used with generic-function name to
write the value of the slot.
Should I take it to mean the same as
:accessor generic-function-name
Specifies that a generic function named generic-function-name
be automatically generated, to read the value of this
slot. SETF may be used with generic-function-name to
write the value of the slot.
********************************************************************
On this topic:
:initialize-only flag
Do we really need this feature? Why not just leave out the
:accessor if we don't want people to be able to setf the slot?
Presumably the :accessor option indicates that a setfable accessor is
made, while its absence still leaves (setf (get-slot ...) ...) available?
Or is GET-SLOT not `agreed to?' If GET-SLOT exists and leaves the slot
setfable, then :initialize-only has a role.
********************************************************************
Danny said: ``There are two different are proposals under discussion.''
He was misguided in saying this. He meant that the West Coast discussion
group was discussing this issue and would probably propose an alternative
that mentions WITH and %WITH (or some such names). We usually discuss
things like this out here to try to filter out bad ideas from the set of
ideas we ship to the Hub.
********************************************************************
Is the name of the type of method combination a symbol for some deep
reason or just to keep it a simple name as in other named things?
*********************************************************************
Are whoppers thought of as being in a different ontological category
from other method combination types? The continue-whopper `feature'
seems to hint so.
-rpg-
∂10-Sep-86 0837 RPG Re: [Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>:
∂09-Sep-86 1947 Bobrow.pa@Xerox.COM Re: [Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>:
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Sep 86 19:47:32 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 SEP 86 18:34:49 PDT
Date: 9 Sep 86 18:34 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: [Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>:
Summary of features we all agree on ]
In-reply-to: Kahn.pa's message of 8 Sep 86 14:07 PDT
To: Kahn.pa@Xerox.COM
cc: Bobrow.pa@Xerox.COM, CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860909-183449-1216@Xerox>
:initialize-only flag
We need to be clear what "after initialization" means. Can one
send an
"initialize-with-plist" message to an "already initialized"
instance?
I think so (How can we stop it?) But that is different than using a
SETF to change the value. Users can almost always get around read-only
declarations not protected by hardware. I prefer the name
:initialize-only to :read-only despite history.
(:meta-class class-name)
There are different uses of meta-classes. There are those that
just
make performance trade-offs and need not be concerned with "the
parsing
of the defclass". It would be reasonable to be able to use the
:meta-class at least in such cases.
I agree.
(MAKE class-name keyword-argument...)
I would prefer that the first argument to MAKE is either a
class-name or
a class.
I agree.
-- danny
∂10-Sep-86 0837 RPG Re: Subtypep
∂09-Sep-86 1947 Bobrow.pa@Xerox.COM Re: Subtypep
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Sep 86 19:47:18 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 SEP 86 17:52:00 PDT
Date: 9 Sep 86 17:46 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: Subtypep
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 08 Sep 86
17:35 PDT
To: RPG@SAIL.STANFORD.EDU
cc: commonloopscore↑.pa@Xerox.COM
Message-ID: <860909-175200-1153@Xerox>
CLASS-OF will be as poorly defined as the current TYPE-OF.
Why is this ill-defined? It is not TYPE-OF. It returns the most
specific class for the instance.
-- danny
∂10-Sep-86 1730 RPG Getting together to work
∂10-Sep-86 1633 Gregor.pa@Xerox.COM Getting together to work
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Sep 86 16:33:27 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 10 SEP 86 15:43:08 PDT
Date: 10 Sep 86 15:42 PDT
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Getting together to work
To: CommonLoopsCore↑.pa@Xerox.COM
cc: Gregor.pa@Xerox.COM
Message-ID: <860910-154308-2286@Xerox>
My messages for the next little while are likely to be more curt than
usual, I can only type with one hand.
We had made a plan to get together monday moring at OOPSLA and work on
the spec. I believe that we will have more work to do than can be done
in three hours.
Instead, I propose that we get together Friday and Saturday after OOPSLA
in Palo Alto. This will give us enough time to actually get some work
done, and takes advantage of existing travel to get a lot of people in
the same place.
I propose that we use the Monday morning at OOPSLA time to have a more
open meeting with people from LMI and HP.
∂11-Sep-86 1057 RPG Things on which we agree
∂10-Sep-86 1919 Owners-commonloopscore↑.pa@Xerox.COM Things on which we agree
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Sep 86 19:19:33 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 10 SEP 86 19:01:23 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.pa@XEROX.ARPA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 10 SEP 86 19:01:07 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 78603;
Wed 10-Sep-86 21:59:43 EDT
Date: Wed, 10 Sep 86 21:59 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Things on which we agree
To: commonloopscore↑.pa@Xerox.COM
In-Reply-To: <860909-232449-1480@Xerox>
Message-ID: <860910215951.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 09 Sep 86 23:24 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Some of the West Coast people prefer MAKE-INSTANCE to MAKE.
The motivation is to leave good names alone when reasonably
short, reasonably descriptive names are available.
Either name is fine with me.
********************************************************************
When I read something like:
:accessor generic-function-name
Specifies that a function named generic-function-name
be automatically generated, to read the value of this
slot. SETF may be used with generic-function name to
write the value of the slot.
Should I take it to mean the same as
:accessor generic-function-name
Specifies that a generic function named generic-function-name
be automatically generated, to read the value of this
slot. SETF may be used with generic-function-name to
write the value of the slot.
I think so. The omission of "generic" before "function" in 1 out of 4
places was probably not intended to mean anything. It should be rephrased
to be consistent.
********************************************************************
On this topic:
:initialize-only flag
Do we really need this feature? Why not just leave out the
:accessor if we don't want people to be able to setf the slot?
Presumably the :accessor option indicates that a setfable accessor is
made, while its absence still leaves (setf (get-slot ...) ...) available?
Or is GET-SLOT not `agreed to?' If GET-SLOT exists and leaves the slot
setfable, then :initialize-only has a role.
Hmm, if you really think get-slot should be customizable this way, then
yes, there should be a slot-option to customize it. Never in a million years
would I have figured out from the name of the slot-option that this is what
it controls, so I think a better name should be found. Except for that,
I'm amenable to putting this in if someone thinks it's important.
I think of get-slot as a subprimitive for getting around the normal
accessor mechanism, so I don't see any point to the extra complexity of
providing ways to turn off get-slot reading and writing. I see even less
point when I think about it harder and suspect that then you would need
a %get-slot, which is the same as get-slot except that it can't be turned
off, as part of the semantics of WITH.
Perhaps other people think of get-slot as something the user would use
all the time, if so that's a bit of a surprise to me. I do think we
agreed that there should be something that does get-slot (called
symbol-value-in-instance in Flavors; I don't much care for either name).
********************************************************************
Danny said: ``There are two different are proposals under discussion.''
He was misguided in saying this. He meant that the West Coast discussion
group was discussing this issue and would probably propose an alternative
that mentions WITH and %WITH (or some such names). We usually discuss
things like this out here to try to filter out bad ideas from the set of
ideas we ship to the Hub.
I haven't been to the Hub in weeks.
********************************************************************
Is the name of the type of method combination a symbol for some deep
reason or just to keep it a simple name as in other named things?
The latter.
*********************************************************************
Are whoppers thought of as being in a different ontological category
from other method combination types? The continue-whopper `feature'
seems to hint so.
Whoppers aren't a method-combination type, they are a kind of method. I
don't know what an ontological category is, but the dictionary
definition of ontological suggests that deleting the word won't change
the meaning of your question. Whoppers (and wrappers) are different
from regular methods because they themselves control the way they get
combined, instead of being controlled by a method-combination routine
defined with define-method-combination.
I should point out again that I don't like whoppers, but I support them
for the standard because I have to admit that my users have found them
very useful. I might not always be the best source of information about
why whoppers are the way they are, for this reason.
∂11-Sep-86 1100 RPG Re: Things on which we agree
∂11-Sep-86 1020 Owners-commonloopscore↑.pa@Xerox.COM Re: Things on which we agree
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 86 10:20:13 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 11 SEP 86 10:03:25 PDT
Redistributed: commonloopscore↑.pa
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 86 10:03:12 PDT
Date: 11 Sep 86 10:03 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: Things on which we agree
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 10 Sep 86 21:59 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: commonloopscore↑.pa@Xerox.COM
Message-ID: <860911-100325-2906@Xerox>
On this topic:
:initialize-only flag
Do we really need this feature? Why not just leave out
the
:accessor if we don't want people to be able to setf the slot?
Presumably the :accessor option indicates that a setfable
accessor
is made, while its absence still leaves (setf (get-slot ...)
...) available? Or is GET-SLOT not `agreed to?' If GET-SLOT
exists and leaves the slot setfable, then :initialize-only has
a
role.
Hmm, if you really think get-slot should be customizable this way,
then
yes, there should be a slot-option to customize it. Never in a
million
years would I have figured out from the name of the slot-option
that
this is what it controls, so I think a better name should be found.
Except for that, I'm amenable to putting this in if someone thinks
it's
important.
What does ":read-only" mean in Flavors on a slot? It was my
understanding that it meant that after initialization, one couldn't set
an instance variable in a method. :initialize-only was put in as a
better name (I thought) for :read-only. Perhaps we should drop it as a
mechanism that must be supported by the system.
Whoppers (and wrappers) are different from regular methods because
they
themselves control the way they get combined, instead of being
controlled by a method-combination routine defined with
define-method-combination.
This of course is how we have always done method combination in Loops,
and it has proven most useful to us. We never allowed super classes to
dictate what a subclass would do. Hence the similarity that I saw
between run-super and continue-whopper. If we have run-super in primary
methods should we have :around methods -- and if so, do you prefer the
name :full-shadow for this type. Ontologically this name is much
sounder, of course, if you like that kind of ontology.
-- danny
∂11-Sep-86 1103 RPG Re: Things on which we agree
∂11-Sep-86 1020 Owners-commonloopscore↑.pa@Xerox.COM Re: Things on which we agree
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 86 10:20:13 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 11 SEP 86 10:03:25 PDT
Redistributed: commonloopscore↑.pa
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 86 10:03:12 PDT
Date: 11 Sep 86 10:03 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: Things on which we agree
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 10 Sep 86 21:59 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: commonloopscore↑.pa@Xerox.COM
Message-ID: <860911-100325-2906@Xerox>
On this topic:
:initialize-only flag
Do we really need this feature? Why not just leave out
the
:accessor if we don't want people to be able to setf the slot?
Presumably the :accessor option indicates that a setfable
accessor
is made, while its absence still leaves (setf (get-slot ...)
...) available? Or is GET-SLOT not `agreed to?' If GET-SLOT
exists and leaves the slot setfable, then :initialize-only has
a
role.
Hmm, if you really think get-slot should be customizable this way,
then
yes, there should be a slot-option to customize it. Never in a
million
years would I have figured out from the name of the slot-option
that
this is what it controls, so I think a better name should be found.
Except for that, I'm amenable to putting this in if someone thinks
it's
important.
What does ":read-only" mean in Flavors on a slot? It was my
understanding that it meant that after initialization, one couldn't set
an instance variable in a method. :initialize-only was put in as a
better name (I thought) for :read-only. Perhaps we should drop it as a
mechanism that must be supported by the system.
Whoppers (and wrappers) are different from regular methods because
they
themselves control the way they get combined, instead of being
controlled by a method-combination routine defined with
define-method-combination.
This of course is how we have always done method combination in Loops,
and it has proven most useful to us. We never allowed super classes to
dictate what a subclass would do. Hence the similarity that I saw
between run-super and continue-whopper. If we have run-super in primary
methods should we have :around methods -- and if so, do you prefer the
name :full-shadow for this type. Ontologically this name is much
sounder, of course, if you like that kind of ontology.
-- danny
∂11-Sep-86 1532 RPG Whoppers and Ontology
∂11-Sep-86 1210 Owners-commonloopscore↑.pa@Xerox.COM Whoppers and Ontology
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 86 12:10:00 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 11 SEP 86 11:43:14 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 11 SEP 86
11:42:51 PDT
Date: 11 Sep 86 11:42 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: Whoppers and Ontology
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860911-114314-3067@Xerox>
Dictionaries are not usually in the business of explaining
philosophical traditions, so I'm not surprised you didn't
find a meaning you could use for `ontological.'
I have the following understanding of whoppers (what I'm about to
explain is a sketch rather than a representation of everything I understand
about them).
Suppose we have a lattice with F1 as the most general (or most basic)
flavor and F2 and F3 increasingly specific. In the flavors documentation
pictorial style, F3 would be at the top of the tree and F1 at the bottom.
In the CommonLoops pictorial style, F1 is at the bottom and F3 at the
top. Consider classical methods only, and suppose there is a whopper
defined on F1 and primary methods on F2 and F3. Suppose that the
whopper does something inconsequential and then does a continue-whopper.
Suppose that the generic function in question is applied to an instance of
F3, then I think the order of execution is the whopper first, then the
method for F3. Is this right? If I am right then Danny's comment that
whoppers are like Loops method combination and continue-whopper is like
run-super is not exactly correct, I think. Aren't whoppers and
continue-whopper like Loops method combination and run-super within the
whopper domain (if there are whoppers in the lattice, then
continue-whopper runs them in most-specific-first order), but that in the
overall order of execution, whoppers get done first then other method
types?
Moon: Is it possible in New Flavors or desirable in the Object System to
mess with the order of execution via method combination defintion (in
Flavors) or changing the disciminating function (in the Object System) so
that the user can define whopper-whoppers, which execute before whoppers?
In other words, are whoppers definable in New Flavors with whoppers
removed?
Gregor: Can you fix the Xerox re-mailer so that lines are not
broken in a funny way?
-rpg-
∂11-Sep-86 1610 RPG Re: Things on which we agree
∂11-Sep-86 1534 Owners-commonloopscore↑.pa@Xerox.COM Re: Things on which we agree
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 86 15:34:49 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 11 SEP 86 14:50:50 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.pa
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 11 SEP 86 14:50:22 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 79135;
Thu 11-Sep-86 17:25:02 EDT
Date: Thu, 11 Sep 86 17:25 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Things on which we agree
To: commonloopscore↑.pa@Xerox.COM
In-Reply-To: <860911-100325-2906@Xerox>
Message-ID: <860911172500.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
[message reformatted to 70-column width to try to avoid linefolding]
Date: 11 Sep 86 10:03 PDT
From: Bobrow.pa@Xerox.COM
On this topic:
:initialize-only flag
Do we really need this feature? Why not just leave out
the :accessor if we don't want people to be able to
setf the slot? [Moon]
Presumably the :accessor option indicates that a setfable
accessor is made, while its absence still leaves (setf
(get-slot ...) ...) available? Or is GET-SLOT not
`agreed to?' If GET-SLOT exists and leaves the slot
setfable, then :initialize-only has a role. [RPG]
Hmm, if you really think get-slot should be customizable this
way, then yes, there should be a slot-option to customize it.
Never in a million years would I have figured out from the
name of the slot-option that this is what it controls, so I
think a better name should be found. Except for that, I'm
amenable to putting this in if someone thinks it's important.
[Moon]
What does ":read-only" mean in Flavors on a slot? It was my
understanding that it meant that after initialization, one
couldn't set an instance variable in a method. :initialize-only
was put in as a better name (I thought) for :read-only. Perhaps
we should drop it as a mechanism that must be supported by the
system. [Bobrow]
There is no ":read-only" feature in Flavors. There is one in
defstruct, but it doesn't tell us much since defstruct is so much
simpler. Let's drop the whole thing unless someone thinks it's
an inportant feature to have.
Whoppers (and wrappers) are different from regular methods
because they themselves control the way they get combined,
instead of being controlled by a method-combination routine
defined with define-method-combination.
This of course is how we have always done method combination in
Loops, and it has proven most useful to us. We never allowed
super classes to dictate what a subclass would do. Hence the
similarity that I saw between run-super and continue-whopper.
I'm not sure this is accurate, but I don't have anything to add beyond
what was in the other message I sent a few minutes ago.
If we have run-super in primary methods should we have :around
methods -- and if so, do you prefer the name :full-shadow for this
type. Ontologically this name is much sounder, of course, if you
like that kind of ontology.
The name :full-shadow doesn't convey much meaning to my ear.
Beyond that, I don't have much to say because I can't figure
out what the specific proposal is.
∂12-Sep-86 0805 RPG specifying metaclass etc.
∂11-Sep-86 1826 Gregor.pa@Xerox.COM specifying metaclass etc.
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 86 18:26:02 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 86 18:19:01 PDT
Date: 11 Sep 86 18:18 PDT
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: specifying metaclass etc.
To: CommonLoopsCore↑.pa@Xerox.COM
cc: Gregor.pa@Xerox.COM
Line-fold: NO
Message-ID: <860911-181901-3531@Xerox>
I was wrong. It does make sense to be able to specify the class
of a class, the class of a generic-function and the class of methods
on that generic-function. For reasons which are complicated, doing
this doesn't buy as much power as it does in PCL, but it still buys
enough power to be worth doing. SO:
add a :class option to defclass
add a :class (or :generic-function-class) option to make-generic and
defgeneric
add a :method-class option to defgeneric and make-generic
∂12-Sep-86 0812 RPG Re: Defmethod syntax proposal
∂11-Sep-86 2205 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Defmethod syntax proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 86 22:05:24 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 11 SEP 86 22:03:45 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 11 SEP 86 22:03:31 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 79317;
Fri 12-Sep-86 01:02:26 EDT
Date: Fri, 12 Sep 86 01:02 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Defmethod syntax proposal
To: CommonLoopsCore↑.PA@Xerox.COM
In-Reply-To: <860911150805.2.GREGOR@AVALON.XEROX-PARC>
Message-ID: <860912010224.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 11 Sep 86 15:08 PDT
From: Gregor.pa@Xerox.COM
Date: Mon, 8 Sep 86 18:41 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Date: 8 Sep 86 13:13 PDT
From: Bobrow.pa@Xerox.COM
I meant that I propose that we not describe classical syntax
as part of the standard. It would simply be a backwards
compatibility feature for Flavors users.
It's really more than that; it provides conceptual compatibility for
people who are familiar with most any of the other existing
object-oriented programming languages, particularly Smalltalk-80.
It provides the familiar concepts of instance variables and "self".
Because of the widespread establishment of these concepts, I think
it's worth putting this into the standard for everyone, despite the
minor inelegance of having two syntaxes when only one is logically
necessary.
Yes, it does provide conceptual compatibility with the other existing
"object-oriented" programming languages. But I place that conceptual
compatibility in the same category as "message passing". Namely that it
is not the model we want to be emphasing to users. This new standard is
generic functions. It isn't message passing. Self and "auto-with" on
self are "message-passing" concepts not generic function concepts.
I don't think we want to be providing support in the standard for
thinking about generic functions as something that they aren't, namely
flavors/smalltalk style "message passing".
I don't agree with the idea that self and "auto-with" have something to
do with message-passing and are therefore obsolete.
Aside from that, I think we are in serious danger of falling into the
trap of trying to make a standard that contains the latest ideas that we
just thought of recently, rather than the stodgy old ideas that are
known to work but aren't any fun any more. Putting in the latest ideas
always sounds good, even to me, but historically it has almost always
resulted in bad standards or standards that aren't widely accepted or
both. Think about the things that everyone hates the most about Common
Lisp, for instance. Some of them are due to trying to be compatible
with older languages, but most of them are due to putting in new things
that seemed well thought out at the time, but in fact were not as well
thought out as we thought. Making a successful standard always includes
making compromises between desire and practice.
If we really think that only the latest ideas are any good, and everything
else should be removed from the standard, then what we are really saying
is that this is the wrong time to make a standard.
For now, the best I can come up with is to propose that it might be
enough to come up with heuristics to tell the two kinds of defmeths
apart instead of just rules. If the heuristics fail to identify the
defmeth for sure than an error would be generated or something.
I don't think anything based on heuristics is going to be acceptable as
a standard. If we have to resort to heuristics then we will be very
much better off using two different names for the two kinds of
method-defining forms.
∂12-Sep-86 1106 RPG Defmethod Syntax
∂12-Sep-86 0842 Owners-commonloopscore↑.pa@Xerox.COM Defmethod Syntax
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 12 Sep 86 08:42:35 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 12 SEP 86 08:40:17 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 12 SEP 86
08:29:28 PDT
Date: 12 Sep 86 08:29 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: Defmethod Syntax
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860912-084017-4039@Xerox>
Moon makes two points. The first is that `self' and `auto-with'
form part of a larger, older tradition of OOP, and we shouldn't
ignore that tradition in order to get the `latest, most final'
ideas in the proposal. He also mentioned that he didn't think
these concepts were inextricably linked to message-passing and are
therefore obsolete.
I believe that these concepts are linked to message-passing, but
not absolutely linked. I think we ought to concentrate on finding
the right abstractions and specifying them; I don't think we should
gratuitously add features that users can implement with our abstractions
simply because `users find them useful.' On the other hand, Moon is
right that it is a mistake to opt for the latest, greatest at the
expense of well-understood concepts. We ought to consider `self'
and `auto-with' more carefully in this light. In other words,
I believe that `self' and `auto-with' are linked to message-passing,
and, even so, they might not be obsolete.
The second point is about distinguishing two forms of defmethod.
I feel it is imperative to find clear rules of distinguishing the
forms rather than invent another defmethod-like form. Only if
the possible syntactic means of distinguishing them are horrendous
should we consider proliferating functions/special forms/macros.
-rpg-
∂12-Sep-86 1108 RPG Re: Defmethod syntax proposal
∂12-Sep-86 0940 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Defmethod syntax proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 12 Sep 86 09:40:26 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 12 SEP 86 09:39:22 PDT
Return-Path: <DLW@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA@XEROX.ARPA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 12 SEP 86 09:08:47 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 79520;
Fri 12-Sep-86 11:56:53 EDT
Date: Fri, 12 Sep 86 11:59 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Re: Defmethod syntax proposal
To: CommonLoopsCore↑.PA@Xerox.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM
In-Reply-To: <860912010224.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <860912115905.1.DLW@CHICOPEE.SCRC.Symbolics.COM>
Date: Fri, 12 Sep 86 01:02 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
I don't agree with the idea that self and "auto-with" have something to
do with message-passing and are therefore obsolete.
Yes. The idea of New Flavors was to get rid of "message passing" and
instead go to "generic functions". We did that, and New Flavors still
has "self" and "auto-with" even though it has "generic functions"
instead of "message passing". Rather, "self" and "auto-with" are
associated with having generic functions with only one argument that's
discriminated on. What makes them go away is not "generic functions",
but "multimethods".
It seems to me that you folks are worried that providing the
"traditional" syntax will discourage users from taking advantage of the
greater power provided by the multimethod capability of the new spec. I
believe that we can take care of this by the organization and phrasing
of the documentation of the spec. We can make it clear that the
"traditional" syntax is stricly weaker than the "modern" syntax, and has
no additional capabilities, and is being provided because the style is
well-known and traditional, rather than because it's considered to be
"better" in any interesting sense.
∂12-Sep-86 1245 RPG Re: Defmethod syntax proposal
∂11-Sep-86 1535 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Defmethod syntax proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 86 15:35:13 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 11 SEP 86 15:10:52 PDT
Redistributed: CommonLoopsCore↑.PA@XEROX.ARPA
Received: from Semillon.ms by ArpaGateway.ms ; 11 SEP 86 15:10:18 PDT
Date: Thu, 11 Sep 86 15:08 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Defmethod syntax proposal
To: DLW@ALDERAAN.SCRC.Symbolics.COM, Bobrow.pa@Xerox.COM,
Moon@STONY-BROOK.SCRC.Symbolics.COM, CommonLoopsCore↑.PA@Xerox.COM
In-Reply-To: <860908223153.1.DLW@CHICOPEE.SCRC.Symbolics.COM>,
The message of 8 Sep 86 16:13-PDT from Bobrow.pa,
<860908184131.4.DLW@CHICOPEE.SCRC.Symbolics.COM>,
The message of 8 Sep 86 13:13-PDT from Bobrow.pa,
<860908125848.1.MOON@EUPHRATES.SCRC.Symbolics.COM>,
The message of 8 Sep 86 09:10-PDT from Bobrow.pa,
<860905205118.7.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<860904180145.6.MOON@EUPHRATES.SCRC.Symbolics.COM>,
The message of 5 Sep 86 10:52-PDT from Bobrow.pa,
The message of 4 Sep 86 13:38-PDT from Bobrow.pa,
<860904150145.7.MOON@EUPHRATES.SCRC.Symbolics.COM>,
The message of 3 Sep 86 18:03-PDT from Bobrow.pa,
<860902235003.8.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<860903004049.0.DLW@CHICOPEE.SCRC.Symbolics.COM>,
<860903004113.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <860911150805.2.GREGOR@AVALON.XEROX-PARC>
Line-fold: no
I think I have digested all the mail on this topic.
Date: 3 Sep 86 18:03 PDT
From: Bobrow.pa
3) :discriminator-class (now called :generic-function-class) and
:method-class are not options of defmethod. They are (advanced)
options of defgeneric.
:discriminator-class and :method-class are not features of defgeneric.
For the same reasons that the :class argument to defclass no longer
exists, these no longer exist.
Date: 8 Sep 86 09:10 PDT
From: Bobrow.pa
In "classical" syntax, no argument of lambda-list can be type
specified. In general syntax at least one must be specifed if
you are using method combination options.
Date: Mon, 8 Sep 86 12:58 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
I don't see why method combination options would be disallowed
for default methods. If it doesn't make sense to allow such
options for default methods, then we can go back to that proposal.
I think it makes perfect sense to have method combination options on
default methods. A :around default method is the canonical example.
Date: Mon, 8 Sep 86 18:41 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Date: 8 Sep 86 13:13 PDT
From: Bobrow.pa@Xerox.COM
I meant that I propose that we not describe classical syntax
as part of the standard. It would simply be a backwards
compatibility feature for Flavors users.
It's really more than that; it provides conceptual compatibility for
people who are familiar with most any of the other existing
object-oriented programming languages, particularly Smalltalk-80.
It provides the familiar concepts of instance variables and "self".
Because of the widespread establishment of these concepts, I think
it's worth putting this into the standard for everyone, despite the
minor inelegance of having two syntaxes when only one is logically
necessary.
Yes, it does provide conceptual compatibility with the other existing
"object-oriented" programming languages. But I place that conceptual
compatibility in the same category as "message passing". Namely that it
is not the model we want to be emphasing to users. This new standard is
generic functions. It isn't message passing. Self and "auto-with" on
self are "message-passing" concepts not generic function concepts.
I don't think we want to be providing support in the standard for
thinking about generic functions as something that they aren't, namely
flavors/smalltalk style "message passing".
I do think we should be providing support in the standard so that an
environment which supports flavors as well as the standard can only have
one defmethod symbol and can unamiguosly determine whether or or not the
defmethod is a flavors defmethod or a CLOS defmethod. I used to think
that was easy until I realized that this also had to work for the kinds
of defmethods that people are going to write using release 7 too.
For now, the best I can come up with is to propose that it might be
enough to come up with heuristics to tell the two kinds of defmeths
apart instead of just rules. If the heuristics fail to identify the
defmeth for sure than an error would be generated or something. Because
I can't figure out how often the heuristics I had in mind might fail I
thought I would send them out to get your all's opinion:
use the name-and-options-syntax:
(defmethod name-and-options args . body)
and used the heuristics:
1. name-and-options is a symbol --> its CLOS for sure
2. one or more of the "required" args is a list --> CLOS for sure
3. cadr of name-and-options is name of a flavor --> probably Flavors
there might be other good rules too.
-------
∂12-Sep-86 1248 RPG Whoppers and Phenomenology
∂11-Sep-86 1534 Owners-commonloopscore↑.pa@Xerox.COM Whoppers and Phenomenology
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 86 15:34:39 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 11 SEP 86 14:40:41 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.pa
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 11 SEP 86 14:40:16 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 79120;
Thu 11-Sep-86 17:14:47 EDT
Date: Thu, 11 Sep 86 17:14 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Whoppers and Phenomenology
To: commonloopscore↑.pa@Xerox.COM
In-Reply-To: <860911-114314-3067@Xerox>
Message-ID: <860911171444.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 11 Sep 86 11:42 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
I have the following understanding of whoppers (what I'm about to
explain is a sketch rather than a representation of everything I understand
about them).
Suppose we have a lattice with F1 as the most general (or most basic)
flavor and F2 and F3 increasingly specific. In the flavors documentation
pictorial style, F3 would be at the top of the tree and F1 at the bottom.
In the CommonLoops pictorial style, F1 is at the bottom and F3 at the
top. Consider classical methods only, and suppose there is a whopper
defined on F1 and primary methods on F2 and F3. Suppose that the
whopper does something inconsequential and then does a continue-whopper.
Suppose that the generic function in question is applied to an instance of
F3, then I think the order of execution is the whopper first, then the
method for F3. Is this right?
Right.
If I am right then Danny's comment that
whoppers are like Loops method combination and continue-whopper is like
run-super is not exactly correct, I think. Aren't whoppers and
continue-whopper like Loops method combination and run-super within the
whopper domain (if there are whoppers in the lattice, then
continue-whopper runs them in most-specific-first order), but that in the
overall order of execution, whoppers get done first then other method
types?
That's right. If you use only whoppers then you can use continue-whopper
and get the same control structure as if you had used only Loops methods
and used run-super.
If on the other hand you have both whoppers and ordinary methods (of
whatever type, primary, :before, or whatever), then all the whoppers get
control before any of the ordinary methods. Another way of saying the
same thing is that in any given whopper all of the ordinary methods,
regardless of how specific the flavor they are attached to, are "inside
of" continue-whopper (along with the whoppers on less specific flavors).
Moon: Is it possible in New Flavors or desirable in the Object System to
mess with the order of execution via method combination defintion (in
Flavors) or changing the disciminating function (in the Object System) so
that the user can define whopper-whoppers, which execute before whoppers?
In other words, are whoppers definable in New Flavors with whoppers
removed?
I think these are two (no, three, maybe four) different questions. Let
me try to answer them separately.
I assume that in Common Lisp with objects the discriminator has control
at some level over whoppers and the user could replace or augment them
by redefining a few methods. I think the discriminator class operates
at a different level of modularity than the method-combination type,
and that it's good for both of these features to exist.
In Flavors, define-method-combination has no control whatsoever over
defwhoppers; they're handled separately.
In Flavors, the user could define a method-combination type that
understood methods with a particular method-option to behave just like
whoppers, or similarly to whoppers but with some modification such as
whopper-whoppers. These couldn't be defined with the existing
defwhopper macro, since define-method-combination has no control over
those. To make those neo-whoppers work with every method-combination
would require modifying every define-method-combination to know about
them. Other than that it's extremely easy.
It's been proposed several times over the years to extend Flavors
whoppers to give the programmer more control over their ordering than
just having the most-specific ones first. None of the proposals ever
got implemented.
Interfaces exist by which the user of New Flavors could define
whopper-whoppers, which execute before regular whoppers, without having
to replace regular whoppers with neo-whoppers. The implementation of
whoppers is in fact table-driven or object-oriented or whatever you want
to call it. However, these interfaces aren't documented and are likely
to change as a result of the project we are currently all engaged in.
∂12-Sep-86 1545 RPG ordering of defclasses
∂12-Sep-86 1416 Gregor.pa@Xerox.COM ordering of defclasses
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 12 Sep 86 14:14:40 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 12 SEP 86 13:11:48 PDT
Date: Fri, 12 Sep 86 13:09 PDT
From: Gregor.pa@Xerox.COM
Subject: ordering of defclasses
To: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860912130952.1.GREGOR@AVALON.XEROX-PARC>
Line-fold: no
In seperate messages, I am going to send out some general comments about
the current draft of the West Coast spec. I am sending these to the
entire list even though I realize that the east coast people haven't
seen this spec, and that they aren't happy about this.
I have been assured that the legal problems with sending the spec to the
east coast have now all been fixed. They weren't big problems, no-one
questions that the spec should be distributed, its just that someone far
from here had to be reminded why they should sign the release ("in my
left hand you see the release form, in my right hand you see a
Louisville Slugger... pick a hand, any hand").
-- Currently the spec makes no statement about when all the included
classes of a class must be defined:
1. They must be defined before the defclass is evaluated. PCL does
this now. I don't like this it makes it harder to order loading of
files for no good reason.
2. They must be defined before an instance of the class is created.
This is what flavors does now and is what I think we should do. It
takes only a very little bit of implementation overhead and provides the
user with nice convenience.
So, these two rules should be added to the spec:
All the classes in the included classes tree of a class must be defined
before it is legal to make an instance of the class.
A class must be defined before it can be mentioned as an argument
specifier in a defmethod.
-------
∂12-Sep-86 1657 RPG Re: Defmethod syntax proposal
∂12-Sep-86 1309 Gregor.pa@Xerox.COM Re: Defmethod syntax proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 12 Sep 86 13:08:57 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 12 SEP 86 12:50:49 PDT
Date: 12 Sep 86 12:48 PDT
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Defmethod syntax proposal
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 12 Sep 86 01:02 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860912-125049-4322@Xerox>
Date: Fri, 12 Sep 86 01:02 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Aside from that, I think we are in serious danger of falling into the
trap of trying to make a standard that contains the latest ideas that we
just thought of recently, rather than the stodgy old ideas that are
known to work but aren't any fun any more ...
... Think about the things that everyone hates the most about Common
Lisp, for instance.
I agree.
If we really think that only the latest ideas are any good, and
everything else should be removed from the standard.
We don't.
I don't think anything based on heuristics is going to be acceptable as
a standard.
Of course, but I wasn't suggesting it as part of the standard. Because I believe
that the classical defmethod has no place in the standard, I was only suggesting
that we should craft the standard in such that in your environment, it should be
possible to distinguish a flavors defmethod from a standard one.
Date: 12 Sep 86 08:29 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
I think we ought to concentrate on finding
the right abstractions and specifying them
I claim that we have. One abstraction is defining a method; that is done with
defmethod. Another abstraction is defining a lexical context in which the slots
of an object can be accessed as if they were variables; that is done with with.
Date: Fri, 12 Sep 86 11:59 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Yes. The idea of New Flavors was to get rid of "message passing" and
instead go to "generic functions". We did that, and New Flavors still
has "self" and "auto-with" even though it has "generic functions"
instead of "message passing".
Frankly, I claim that is an inelegance in the design of new flavors.
What makes them go away is not "generic functions",
but "multimethods".
No, I think that generic functions makes them go away. What multimethods
do is make it clear that generic functions should make self and auto-with go
away. Multimethods, being the general case of generic functions make it
clear that it is wrong to think of any single distinguished argument to a
generic function as somehow having a greater status than the others.
It seems to me that you folks are worried that providing the
"traditional" syntax will discourage users from taking advantage of the
greater power provided by the multimethod capability of the new spec. I
believe that we can take care of this by the organization and phrasing
of the documentation of the spec.
I agree that documentation can go a long way towards making it clear that
classical defmethod syntax is an abbreviation for a defmethod and a with.
But I don't think we are worried about what you suggest we are. I frankly
think that extending the behavior of the standard defmeth so that it does
auto-with is conceptually in-elegant.
But I agree that it provides a convenience that many people have grown
used to. So, given appropriate documentation, and a design for arguments
to defmethod which is nice, I might be willing to concede on this issue. But
I suspect that we are going to have to go to having to seperate names for
these things, which is where we were two weeks ago (but they were the
wrong names).
∂12-Sep-86 1752 RPG ordering of defclasses
∂12-Sep-86 1701 Owners-CommonLoopsCore↑.pa@Xerox.COM ordering of defclasses
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 12 Sep 86 17:01:03 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 12 SEP 86 14:35:40 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa@XEROX.ARPA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 12 SEP 86 14:23:33 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 102194; Fri
12-Sep-86 17:22:45 EDT
Date: Fri, 12 Sep 86 17:22 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: ordering of defclasses
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860912130952.1.GREGOR@AVALON.XEROX-PARC>
Message-ID: <860912172209.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Fri, 12 Sep 86 13:09 PDT
From: Gregor.pa@Xerox.COM
Currently the spec makes no statement about when all the included
classes of a class must be defined:
1. They must be defined before the defclass is evaluated. PCL does
this now. I don't like this it makes it harder to order loading of
files for no good reason.
2. They must be defined before an instance of the class is created.
This is what flavors does now and is what I think we should do. It
takes only a very little bit of implementation overhead and provides the
user with nice convenience.
So, these two rules should be added to the spec:
All the classes in the included classes tree of a class must be defined
before it is legal to make an instance of the class.
A class must be defined before it can be mentioned as an argument
specifier in a defmethod.
Flavors in fact requires that all of the component flavors must be
defined before you can do a defmethod. I believe the reason for this
applies to Common Lisp Classes as well, and would translate into a third
rule:
All the classes in the included classes tree of a class must be
defined (known to the compiler) before it is legal to
evaluate (compile) a WITH.
With this addition, I agree.
∂12-Sep-86 1756 RPG Getting together to work
∂12-Sep-86 1701 Owners-CommonLoopsCore↑.pa@Xerox.COM Getting together to work
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 12 Sep 86 17:00:00 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 12 SEP 86 13:31:52 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 12 SEP 86 13:06:28 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 79640;
Fri 12-Sep-86 14:34:31 EDT
Date: Fri, 12 Sep 86 14:34 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Getting together to work
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860910-154308-2286@Xerox>
Message-ID: <860912143428.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 10 Sep 86 15:42 PDT
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
We had made a plan to get together monday moring at OOPSLA and work on
the spec. I believe that we will have more work to do than can be done
in three hours.
Instead, I propose that we get together Friday and Saturday after OOPSLA
in Palo Alto. This will give us enough time to actually get some work
done, and takes advantage of existing travel to get a lot of people in
the same place.
I talked about this with Dan and Sonya. We agree that we need a face to face
meeting, but we're not sure about the timing. We all think it would be better
to have the meeting before OOPSLA rather than after, so that at OOPSLA we are
all telling the same story to people we talk to. Also we promised at the Lisp
conference that we would hand something out at OOPSLA showing our progress,
and it seems like a good idea to have a face to face meeting to finalize what
goes into that document.
If we're going to meet before OOPSLA there are some constraints. Dan is not
available until the 24th. Dan and I are not available on the 26th. Sonya
can't really spend a whole week away from the office. There seem to be several
possibilities:
Meet on the weekend Sep 27-28, or just Sep 28, either in Palo Alto or in
Portland. It's probably possible for us to fly out Friday night, but
obviously a one-day meeting would be a little easier logistically than a
two-day meeting. I don't know if one day is enough.
Meet on Thursday Sep 25 either in Cambridge or in Washington (this is the day
after the X3J13 meeting).
We also need to start talking through the mail about what excatly we're going
to have ready to hand out to the public at OOPSLA.
I propose that we use the Monday morning at OOPSLA time to have a more
open meeting with people from LMI and HP.
This sounds good.
∂13-Sep-86 2051 RPG Defmethod syntax
∂12-Sep-86 2126 Owners-CommonLoopsCore↑.PA@Xerox.COM Defmethod syntax
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 12 Sep 86 21:26:06 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 12 SEP 86 21:24:12 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 12 SEP 86 21:23:51 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 79829;
Sat 13-Sep-86 00:22:32 EDT
Date: Sat, 13 Sep 86 00:22 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Defmethod syntax
To: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860913002227.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
I've read all the mail on this again and I'd like to try to converge
on something that we can all agree on. This message is an attempt to
lay out all the issues without including any advocacy.
I think we can decide on the syntax of defmethod independent of issues
of discriminating on optional arguments, whether defgeneric is required
or optional, the abbreviated form of WITH that Danny Bobrow mentioned
(discussed in a separate message), and whether the syntax for classical
methods is a required or optional part of the standard. (The syntax for
classical methods has to be provided for in some form in order to meet
the goal of migration through mechanical translation that we set for
ourselves last month, as you recall.)
I see three viable proposals. I will give each proposal in the BNF
variant explained on page 8 of Common Lisp: the Language, except that
lowercase means italics and uppercase means roman, along with six
examples (the first lines of the same six methods for each). The six
examples are: a multimethod without options; a multimethod with an
option; a default method without options; a default method with an
option; a classical method without options; and a classical method with
an option.
Each proposal actually comes in (a) and (b) forms, depending on what we
do about SETF. That's discussed after the basic proposals. Definitions
of nonterminal symbols are at the end of this message, so they don't
get in the way.
THREE VIABLE PROPOSALS:
(1) Unparenthesized Options
General syntax:
(DEFMETHOD generic-function {option}*
{lambda-list | qualified-lambda-list}
{declaration | doc-string}*
{form}*)
Classical syntax:
(DEFMETHOD (generic-function self-class {option}*)
{lambda-list | qualified-lambda-list}
{declaration | doc-string}*
{form}*)
(defmethod foo ((a c1) (b c2))
(defmethod foo :before ((a c1) (b c2))
(defmethod foo (a b)
(defmethod foo :before (a b)
(defmethod (foo c1) (b)
(defmethod (foo c1 :before) (b)
(2) Untyped Arglist
General syntax:
(DEFMETHOD generic-function
{lambda-list | qualified-lambda-list}
{declaration | doc-string}*
{form}*)
and
(DEFMETHOD (generic-function {option}*)
qualified-lambda-list
{declaration | doc-string}*
{form}*)
Classical syntax:
(DEFMETHOD (generic-function self-class {option}*)
lambda-list
{declaration | doc-string}*
{form}*)
(defmethod foo ((a c1) (b c2))
(defmethod (foo :before) ((a c1) (b c2))
(defmethod foo (a b)
(defmethod (foo :before) ((a t) b)
(defmethod (foo c1) (b)
(defmethod (foo c1 :before) (b)
(3) Two Names
General syntax:
(DEFINE-METHOD generic-function
{lambda-list | qualified-lambda-list}
{declaration | doc-string}*
{form}*)
and
(DEFINE-METHOD (generic-function {option}*)
{lambda-list | qualified-lambda-list}
{declaration | doc-string}*
{form}*)
Classical syntax:
(DEFMETHOD (generic-function self-class {option}*)
{lambda-list | qualified-lambda-list}
{declaration | doc-string}*
{form}*)
(define-method foo ((a c1) (b c2))
(define-method (foo :before) ((a c1) (b c2))
(define-method foo (a b)
(define-method (foo :before) (a b)
(defmethod (foo c1) (b)
(defmethod (foo c1 :before) (b)
SETF VARIANTS:
There are two different ways to add the ability to define methods for
SETF of a generic function to each proposal:
(a) Tack -SETF onto the special form name.
(b) Replace generic-function with (SETF generic-function).
In both variants, a setf-lambda-list is inserted between the regular
lambda-list and the {declaration | doc-string}* that begins the body.
DRAWBACKS OF EACH PROPOSAL:
(1) lambda-list is not always the second subform of DEFMETHOD.
(2) In general syntax, you cannot use options without having a
qualified-lambda-list rather than a plain lambda-list. In other
words, a default daemon method has to have an extra t in it.
Classical syntax cannot be used to write multi-methods.
Classical syntax is a bit harder to identify at a glance,
although it's not syntactically ambiguous.
(3) Twice as many special forms.
(a) Twice as many special forms. Need DEFGENERIC-SETF, too.
(b) Funny syntax, SETF in the car of a list means something different
from other symbols in the car of a list, i.e. the cdr of the list is not
{option}*. Also SETF in the generic function changes the parsing of the
rest of the defmethod.
NONTERMINALS:
generic-function -- a symbol that names the generic function
being specialized.
self-class -- a symbol that names the class of the first argument.
option -- a non-nil symbol or a number, used by method
combination to identify the method.
lambda-list -- as defined in CLtL p.60.
qualified-lambda-list -- a lambda-list with at least one
variable replaced by a type-qualified variable
so that discrimination occurs on that argument.
setf-lambda-list -- {lambda-list | qualified-lambda-list}
except that for now there can be only one parameter.
declaration, doc-string, form -- as defined in CLtL.
∂13-Sep-86 2100 RPG abbreviated form of WITH
∂12-Sep-86 2131 Owners-CommonLoopsCore↑.PA@Xerox.COM abbreviated form of WITH
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 12 Sep 86 21:31:41 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 12 SEP 86 21:30:40 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 12 SEP 86 21:30:21 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 79830;
Sat 13-Sep-86 00:28:43 EDT
Date: Sat, 13 Sep 86 00:28 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: abbreviated form of WITH
To: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860913002840.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Elaborating on something Danny Bobrow mentioned, it would be possible
to extend the syntax of argument qualifications to provide an automatic
WITH. The optional prefix-name and type-name arguments to WITH should
be optionally specifiable. This syntax can be used on more than one
argument, but the program is invalid if there are any name conflicts,
just as in LET and just as in WITH with more one name-specification.
This seems like a good idea. There are several ways it could be done,
let me try and propose some. The syntax is the syntax for a
discriminating parameter specifier, in the BNF variant explained on page
8 of Common Lisp: the Language, except that lowercase means italics and
uppercase means roman.
(1) (variable class :WITH-VARS [prefix-name [type-name]])
(2) (variable :INSIDE class [prefix-name [type-name]])
(3) (variable class :WITH T [:PREFIX prefix-name] [:CLASS type-name])
(4) (variable :CLASS class :WITH T [:PREFIX prefix-name])
In all of these, the meaning of (variable class) is not changed.
You who are reading this will probably come up with some better ideas.
∂13-Sep-86 2101 RPG Re: Defmethod syntax
∂13-Sep-86 1550 Masinter.pa@Xerox.COM Re: Defmethod syntax
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 13 Sep 86 15:50:29 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 13 SEP 86 10:50:44 PDT
Date: 13 Sep 86 10:51 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Defmethod syntax
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sat, 13 Sep 86 00:22 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860913-105044-4936@Xerox>
(4) two other names:
General syntax:
(DEFMETHOD {generic-function | (generic-function {option}*)}
{lambda-list | qualified-lambda-list}
{declaration | doc-string}*
{form}*)
(This combines the forms of your (2), and is upward compatible with DEFUN)
and
Classical syntax:
(DEFINE-CLASSICAL-METHOD (generic-function self-class {option}*)
lambda-list
{declaration | doc-string}*
{form}*)
∂14-Sep-86 1112 Gregor.pa@Xerox.COM Re: Getting together to work
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 86 11:12:35 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 SEP 86 11:11:21 PDT
Date: 14 Sep 86 11:11 PDT
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Getting together to work
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 12 Sep 86 14:34 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860914-111121-5339@Xerox>
Danny can't make it anytime between Washington and Oopsla.
DLW can't make it until the 24th.
During Washington or OOPSLA there isn't enough time (or peace and quiet).
In your message, you say "Sonya can't really spend a whole week away
from the office." Does this mean that Sonya can't make it after OOPSLA
(because she is going to OOPSLA)?
If in fact Sonya can't make it right after OOPSLA then I don't see any way
that we are going to be able to take advantage of the travel we are going to
be making anyways to get together. But I do think we should get together
real soon. Would you all be interested in coming out here the week after
OOPSLA?
∂14-Sep-86 1118 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: ordering of defclasses
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 86 11:18:26 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 14 SEP 86 11:14:41 PDT
Redistributed: CommonLoopsCore↑.pa
Received: from Cabernet.ms by ArpaGateway.ms ; 14 SEP 86 11:14:27 PDT
Date: 14 Sep 86 11:14 PDT
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: ordering of defclasses
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 12 Sep 86 17:22 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860914-111441-5341@Xerox>
Date: Fri, 12 Sep 86 17:22 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Flavors in fact requires that all of the component flavors must be
defined before you can do a defmethod. I believe the reason for this
applies to Common Lisp Classes as well, and would translate into a third
rule:
All the classes in the included classes tree of a class must be
defined (known to the compiler) before it is legal to
evaluate (compile) a WITH.
With this addition, I agree.
Right.
∂14-Sep-86 1622 Gregor.pa@Xerox.COM Method Naming and Identity Proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 86 16:22:34 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 14 SEP 86 16:11:31 PDT
Date: Sun, 14 Sep 86 16:10 PDT
From: Gregor.pa@Xerox.COM
Subject: Method Naming and Identity Proposal
To: Moon@STONY-BROOK.SCRC.Symbolics.COM, CommonLoopsCore↑.PA@Xerox.COM
In-Reply-To: <860902233747.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <860914161007.3.GREGOR@AVALON.XEROX-PARC>
Line-fold: no
I am not sure what you mean by making the concept of the names and
identities of methods precise. Or what it is about the identities of
methods you want to specify.
Is this just for portable environment features like TRACE? If so then I
agree that we need to specify a way to tell trace to trace a particular
method, but I don't believe we need to specify the kind of functionality
that comes to mind when I think of method names.
-------
∂14-Sep-86 1817 Gregor.pa@Xerox.COM default optional arguments to a generic function
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 86 18:16:59 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 14 SEP 86 18:06:04 PDT
Date: Sun, 14 Sep 86 18:04 PDT
From: Gregor.pa@Xerox.COM
Subject: default optional arguments to a generic function
To: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860914180428.4.GREGOR@AVALON.XEROX-PARC>
Line-fold: no
For clarity, this message assumes that you have to do a defgeneric
before a defmethod. I don't want to make up my mind about having to do
a defgeneric before a defmethod until I understand this issue of
defaulting optional arguments.
I have tried to process all the preceding mail on this subject. Forgive
me if I have just re-iterated an existing position.
As terminology:
GENERIC FUNCTION DEFAULTING is when the generic function proper
provides default values for optional arguments to the generic
function. In the kind of generic function defaulting I am talking
about, the defaulted values are used as part of the method lookup
and passed on to whichever method is invoked.
METHOD DEFAULTING is when a particular method provides default
values for some of its arguments.
In this variant of generic function defaulting, it signals an error to
attempt to define a method on a generic function which accepts less than
the number of arguments that the generic function defaulting can
produce. Here is an example:
(defgeneric draw (thing place &optional (clip-mask *clip-mask*)) ..)
This defmethod is legal:
(defgeneric draw ((thing block) (place window) clip-mask) ..)
But this defmethod is not:
(defgeneric draw ((thing block) (place window)) ..)
Moon's variant of generic function defaulting, in which the defaulted
values are dropped on the floor after method lookup does not have this
problem. Each method must accept only as many required arguments as the
generic function proper.
So, I see two different schemes for generic function defaulting:
GFD #1. the defaults from the defgeneric are used only for method
lookup. This is the kind I described above.
GFD #2. the defaults from the defgeneric are used for method lookup
and also passed to the method.
There is a fundamental conceptual difference here. I am not sure which
I prefer, but I am leaning towards number 1. Because...
Date: Thu, 4 Sep 86 16:15 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
(make-specializable 'print)
This is the same as:
(defgeneric print (object &optional stream))
(defmethod print (x &optional ((stream gee-whiz-display))) ...)
But (let ((*standard-output* <instance of the gee-whiz-display>))
(print <lisp-object>))
calls the wrong method! This is what I have been complaining about all
along. This is the key issue.
I agree that this is the key issue. Using GFD #1, there is no problem.
You would have to specify a default value for the second argument to the
PRINT generic function as a whole:
(defgeneric print (object &optional (stream *standard-output*))
Then the example:
(let ((*standard-output* <instance of the gee-whiz-display>))
(print <lisp-object>))
would get the right method.
-------
∂14-Sep-86 1837 Owners-commonloopscore↑.pa@Xerox.COM Method Identification
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 86 18:37:23 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 14 SEP 86 18:32:19 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 14 SEP 86
18:32:09 PDT
Date: 14 Sep 86 18:31 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: Method Identification
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860914-183219-5434@Xerox>
Presumably a method is identified by the pair of its generic function
and its argument signature (the classes of the arguments). Also,
presumably, the function FIND-METHOD uses this pair.
-rpg-
------- End undelivered message -------
∂15-Sep-86 1152 Owners-commonloopscore↑.pa@Xerox.COM Method Identification
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 86 11:52:02 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 SEP 86 10:38:36 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.pa
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 15 SEP 86 10:37:26 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 80351;
Mon 15-Sep-86 13:34:06 EDT
Date: Mon, 15 Sep 86 13:34 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Method Identification
To: commonloopscore↑.pa@Xerox.COM
In-Reply-To: <860914-183219-5434@Xerox>
Message-ID: <860915133401.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 14 Sep 86 18:31 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Presumably a method is identified by the pair of its generic function
and its argument signature (the classes of the arguments). Also,
presumably, the function FIND-METHOD uses this pair.
You forgot some things, such as the method-options. This was discussed
extensively in my message of 2 Sep 86, message ID
<860902233747.7.MOON@EUPHRATES.SCRC.Symbolics.COM>.
∂15-Sep-86 1152 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Defmethod syntax
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 86 11:52:11 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 SEP 86 10:42:43 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 15 SEP 86 10:38:41 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 80355;
Mon 15-Sep-86 13:37:12 EDT
Date: Mon, 15 Sep 86 13:37 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Defmethod syntax
To: CommonLoopsCore↑.PA@Xerox.COM
In-Reply-To: <860913-105044-4936@Xerox>
Message-ID: <860915133708.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 13 Sep 86 10:51 PDT
From: Masinter.pa@Xerox.COM
(4) two other names:
General syntax:
(DEFMETHOD {generic-function | (generic-function {option}*)}
{lambda-list | qualified-lambda-list}
{declaration | doc-string}*
{form}*)
(This combines the forms of your (2), and is upward compatible with DEFUN)
and
Classical syntax:
(DEFINE-CLASSICAL-METHOD (generic-function self-class {option}*)
lambda-list
{declaration | doc-string}*
{form}*)
This would be fine except that it violates the goal we set for ourselves
last month of providing smooth migration paths for existing users of
Flavors and Portable Common Loops. Since you can't tell a new-style
DEFMETHOD from a Flavors DEFMETHOD, it would be impossible to provide
incremental mechanical translation. I don't think we should contemplate
abandoning that goal without a more compelling reason than merely liking
the spelling DEFMETHOD more than any other.
∂15-Sep-86 1152 Owners-CommonLoopsCore↑.PA@Xerox.COM Method Naming and Identity Proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 86 11:52:27 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 SEP 86 10:48:48 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 15 SEP 86 10:44:48 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 80362;
Mon 15-Sep-86 13:43:29 EDT
Date: Mon, 15 Sep 86 13:43 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Method Naming and Identity Proposal
To: CommonLoopsCore↑.PA@Xerox.COM
In-Reply-To: <860914161007.3.GREGOR@AVALON.XEROX-PARC>
Message-ID: <860915134324.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: Sun, 14 Sep 86 16:10 PDT
From: Gregor.pa@Xerox.COM
I am not sure what you mean by making the concept of the names and
identities of methods precise. Or what it is about the identities of
methods you want to specify.
To quote from my message of 2 Sep, which your message is a reply to:
"The key property of these names is that when two defmethod forms with the same
name (according to the EQUAL function) are evaluated, the second defmethod
replaces the method defined by the first defmethod, rather than defining a
second method."
Is this just for portable environment features like TRACE?
What would be needed for TRACE is a further extension, not merely making the
concept of method identity precise, but also reifying it as a Lisp
object that can be used as the method's name in the arguments to TRACE.
I wasn't proposing that, since it seems to be leaving the area of object
oriented programming and getting into other parts of the Common Lisp
specification. To quote again from my message:
"In an implementation that has function-specs, these lists can be used as
function-specs to access the method's definition, trace it, and so forth.
In other implementations I guess there is no way to perform those operations."
In other words, I'm not proposing to require every implementation to have
function-specs (I would certainly like to, but not as part of the
object-oriented programming proposal).
I think I should have been clearer about what I meant by an identity and
what I meant by a name. If the above hasn't clarified it, let me know and
I'll work harder on it.
If so then I
agree that we need to specify a way to tell trace to trace a particular
method, but I don't believe we need to specify the kind of functionality
that comes to mind when I think of method names.
What functionality is that?
∂15-Sep-86 1437 Owners-CommonLoopsCore↑.pa@Xerox.COM default optional arguments to a generic function
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 86 14:34:39 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 SEP 86 12:26:13 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 15 SEP 86 12:25:35 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 80419;
Mon 15-Sep-86 15:24:38 EDT
Date: Mon, 15 Sep 86 15:24 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: default optional arguments to a generic function
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860914180428.4.GREGOR@AVALON.XEROX-PARC>
Message-ID: <860915152433.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: Sun, 14 Sep 86 18:04 PDT
From: Gregor.pa@Xerox.COM
For clarity, this message assumes that you have to do a defgeneric
before a defmethod. I don't want to make up my mind about having to do
a defgeneric before a defmethod until I understand this issue of
defaulting optional arguments.
I have tried to process all the preceding mail on this subject. Forgive
me if I have just re-iterated an existing position.
As terminology:
GENERIC FUNCTION DEFAULTING is when the generic function proper
provides default values for optional arguments to the generic
function. In the kind of generic function defaulting I am talking
about, the defaulted values are used as part of the method lookup
and passed on to whichever method is invoked.
METHOD DEFAULTING is when a particular method provides default
values for some of its arguments.
In this variant of generic function defaulting, it signals an error to
attempt to define a method on a generic function which accepts less than
the number of arguments that the generic function defaulting can
produce. Here is an example:
(defgeneric draw (thing place &optional (clip-mask *clip-mask*)) ..)
This defmethod is legal:
(defgeneric draw ((thing block) (place window) clip-mask) ..)
But this defmethod is not:
(defgeneric draw ((thing block) (place window)) ..)
Moon's variant of generic function defaulting, in which the defaulted
values are dropped on the floor after method lookup does not have this
problem. Each method must accept only as many required arguments as the
generic function proper.
In my proposal of 2 September I had intended to require that each method
must accept the same number of arguments as the generic function. My
proposal could be read otherwise if you believe that "is an error" means
the programmer can do it anyway, but I hadn't intended to propose that.
I think we all agree that requiring that the minimum number of arguments,
maximum number of arguments, and keyword parameter keywords be consistent
between all methods and the generic function is acceptable, at least I
don't recall anyone arguing against it and several people have proposed it.
So, I see two different schemes for generic function defaulting:
GFD #1. the defaults from the defgeneric are used only for method
lookup. This is the kind I described above.
GFD #2. the defaults from the defgeneric are used for method lookup
and also passed to the method.
Actually, the kind you described above seems to me to be GFD #2.
But that's not important, unless it means that I have completely
misunderstood what you're saying. I think the breakdown into GFD #1
and GFD #2 really clarifies what's going on here.
There is a fundamental conceptual difference here. I am not sure which
I prefer, but I am leaning towards number 1. Because...
My proposal of 2 September was intended to eliminate the distinction
between these by declaring invalid any program that can tell the difference.
I guess that was not very clear in the proposal. Does anyone have reasons
why programs that can tell the difference between GFD #1 and GFD #2 should
be allowed? This would mean that the optional argument would be defaulted
to one value for method selection and then be defaulted to a different value
in the actual method, or else not accepted as an argument at all if we
didn't require the defmethod and defgeneric arguments to be consistent.
If there is no reason to allow programs that can tell the difference between
GFD #1 and GFD #2, then I think we should forbid them, since obviously this
leads to confusion.
Date: Thu, 4 Sep 86 16:15 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
(make-specializable 'print)
This is the same as:
(defgeneric print (object &optional stream))
(defmethod print (x &optional ((stream gee-whiz-display))) ...)
But (let ((*standard-output* <instance of the gee-whiz-display>))
(print <lisp-object>))
calls the wrong method! This is what I have been complaining about all
along. This is the key issue.
I agree that this is the key issue. Using GFD #1, there is no problem.
You would have to specify a default value for the second argument to the
PRINT generic function as a whole:
(defgeneric print (object &optional (stream *standard-output*))
Then the example:
(let ((*standard-output* <instance of the gee-whiz-display>))
(print <lisp-object>))
would get the right method.
-------
This example is obscured by the unclarity of the definition of
PRINT in the Common Lisp manual, which makes it unclear exactly where the
substitution of the value of *standard-output* for an unsupplied second
argument happens. I in fact thought when I sent that message that
(make-specializable 'print) would be the same as (defgeneric print
(object &optional (stream *standard-output*)), but I hadn't read CLtL
carefully enough to realize that PRINT accepts NIL as a stream argument.
Of course we don't really want to specialize PRINT anyway, since it's
the function that outputs a carriage return before the object and a
space after. What we really want to specialize is the internal
function, not named by CLtL, that is called by all of PRINT, PRIN1,
PRINC, PPRINT, WRITE, FORMAT ~S, PRIN1-TO-STRING, etc. But that ruins
the example, since surely that internal function has the stream as
a required argument, not an optional one.
- - -
I think that we are actually in complete agreement here. For an optional
argument to be used for discrimination, the defaulting has to be in the
defgeneric. Now we can decide whether, when you do a defmethod without
first doing a defgeneric, it signals an error or generates an implied
defgeneric according to well-defined rules.
I think we also agree that the arglists of generic functions and methods
must be consistent; we need to define precisely what that means, but
intuitively I think it means that they are equal except for the names of
the arguments and the type qualifications in the methods. Seeing the
confusion that can arise from subtle inconsistencies, e.g. different
default values for optional arguments, I now favor requiring stronger
consistency than mere agreement of number of arguments. This needs to
be refined to a more precise specification; if people agree with the
intuitive specification I will volunteer to produce a precise
specification for consideration.
Does anyone disagree that we agree?
∂15-Sep-86 1436 Masinter.pa@Xerox.COM Re: Defmethod syntax
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 86 14:34:48 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 SEP 86 14:20:18 PDT
Date: 15 Sep 86 14:22 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Defmethod syntax
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 15 Sep 86 13:37 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860915-142018-6089@Xerox>
sorry... I was off the mailing list for a while, and missed the earlier
discussion.
I'm happy with spelling the new way of defining methods some other way
than "defmethod". I don't care what the name is exactly, but I'd like it
to be short & simple to remember; I thought define-method was too long.
(I originally long ago proposed spelling it "defun".)
Here's some more names
defpartial (defines a partial function)
defmeth (shorter than define-method, but otherwise an unfortunate
abbrev)
deffunction (I know this is longer, but it emphasizes the "function"
nature
of the beast well enough that I include it)
deffn even shorter than defun, defines "partial functions" (don't
groan)
I like this one the most. You can make a function into a method
with a single character delete.
∂15-Sep-86 1436 Owners-commonloopscore↑.pa@Xerox.COM Goals of the Specification
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 86 14:34:30 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 SEP 86 12:20:39 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 15 SEP 86
12:20:21 PDT
Date: 15 Sep 86 12:20 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: Goals of the Specification
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860915-122039-5943@Xerox>
It is difficult to design for a set of goals set in a meeting
that hardly anyone attened. Masinter did not attend it; neither
did I. You cannot blame us for tryin to use only good design criteria
rather than these hidden goals.
I would say that the goals of backwards compatibility are admirable
as long as they don't imply a poorer design. We will probably have
to live with the new specification longer than the switchover period.
One can claim that Common Lisp itself is a poorer language because
it had to be compatible with MacLisp and like other existing Lisps.
I have few problems with requiring additional Common Lispage as part
of the CommonLos spec.
-rpg-
∂15-Sep-86 1615 Owners-commonloopscore↑.pa@Xerox.COM Goals of the Specification
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 86 16:15:47 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 SEP 86 15:58:51 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.pa
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 15 SEP 86 15:58:13 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 80550;
Mon 15-Sep-86 18:44:05 EDT
Date: Mon, 15 Sep 86 18:44 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Goals of the Specification
To: commonloopscore↑.pa@Xerox.COM
In-Reply-To: <860915-122039-5943@Xerox>
Message-ID: <860915184400.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 15 Sep 86 12:20 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
It is difficult to design for a set of goals set in a meeting
that hardly anyone attened. Masinter did not attend it; neither
did I. You cannot blame us for tryin to use only good design criteria
rather than these hidden goals.
The goals weren't set in that four-person meeting at MIT on Friday after
the Lisp conference, but in earlier discussion that I thought you were
involved in (but I might be remembering wrong). There was a policy
statement that we decided we weren't ready to hand out during the Lisp
Conference (or the object-oriented programming committee meeting that
coincided with the Lisp conference) which contained the goals. I agree
that I erred in assuming that everyone on this mailing list had already
bought into a particular list of goals (in fact I have no idea who is
the complete population of this mailing list).
In any case, if we don't even agree on the goals of this project, we'd
better bring that out into the open and agree on some goals as soon as
possible. Having heard almost nothing from you, I can only go on what
I have. We Symbolics people are about to net-mail out a proposed
statement of goals, which can serve as a starting point for discussion.
Maybe that will help.
I would say that the goals of backwards compatibility are admirable
as long as they don't imply a poorer design. We will probably have
to live with the new specification longer than the switchover period.
One can claim that Common Lisp itself is a poorer language because
it had to be compatible with MacLisp and like other existing Lisps.
One has.
I have few problems with requiring additional Common Lispage as part
of the CommonLos spec.
Again this is a question of goals. Is it more important to make it easy
for every Common Lisp implementation to implement this spec, or to make
the spec include all the good ideas we might have thought of? The only
statement of goals for this project I have ever seen speaks of simplicity
and implementability.
∂15-Sep-86 1743 Masinter.pa@Xerox.COM Re: Goals of the Specification
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 86 17:43:34 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 SEP 86 16:17:58 PDT
Date: 15 Sep 86 16:15 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Goals of the Specification
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 15 Sep 86 18:44 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: commonloopscore↑.pa@Xerox.COM
Message-ID: <860915-161758-6228@Xerox>
The current list contents of commonloopscore↑.pa@xerox.com is:
Bobrow.pa Common-Lisp-Class-archive@Stony-Brook.SCRC.Symbolics.COM
COMMON-LISP-OBJECT-SYSTEM@SU-AI.ARPA
CommonLoops-Spec-Archive@AI.AI.MIT.EDU DLW@QUABBIN.SCRC.Symbolics.COM
edsel!lgd@navajo.stanford.edu Gregor.pa Kahn.pa Lanning.pa
LGD@SU-AI.arpa Masinter.pa Moon@STONY-BROOK.SCRC.Symbolics.COM
SKeene@STONY-BROOK.SCRC.Symbolics.COM
I assume RPG gets the mail via COMMON-LISP-OBJECT-SYSTEM@SU-AI.ARPA,
although I don't know who else does. I'm not sure who LDG is (I assume
someone at Lucid) or SKeene@STONY-BROOK.SCRC.Symbolics.COM.
I don't think I object to what I've heard of the goals, I just didn't
see the list. Avoiding obvious name conflicts with Flavors and allowing
mechanical translation of Flavors, while a bow to backward
compatibility, is not an onerous one.
∂15-Sep-86 2005 Owners-CommonLoopsCore↑.PA@Xerox.COM Defmethod syntax
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 86 20:04:12 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 SEP 86 19:22:39 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 15 SEP 86 19:22:24 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 80612;
Mon 15-Sep-86 22:20:24 EDT
Date: Mon, 15 Sep 86 22:20 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Defmethod syntax
To: CommonLoopsCore↑.PA@Xerox.COM
In-Reply-To: <860913002227.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <860915222018.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
I prefer (1b), with (1a) a close second. (2) has too many funny
restrictions and (3) has too many special form names.
∂15-Sep-86 2101 Owners-CommonLoopsCore↑.pa@Xerox.COM default optional arguments to a generic function
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 86 21:01:37 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 SEP 86 20:59:04 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa@XEROX.ARPA
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 15 SEP 86 20:58:46 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 80635;
Mon 15-Sep-86 23:57:49 EDT
Date: Mon, 15 Sep 86 23:57 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: default optional arguments to a generic function
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860915152433.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <860915235743.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: Mon, 15 Sep 86 15:24 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
I have a bit more to say on this topic. I'll try to keep it short.
Date: Sun, 14 Sep 86 18:04 PDT
From: Gregor.pa@Xerox.COM
...So, I see two different schemes for generic function defaulting:
GFD #1. the defaults from the defgeneric are used only for method
lookup. This is the kind I described above.
GFD #2. the defaults from the defgeneric are used for method lookup
and also passed to the method.
There is a fundamental conceptual difference here. I am not sure which
I prefer, but I am leaning towards number 1.
A good reason to prefer GFD #1 is that it doesn't interfere with
supplied-p parameters in the methods. This is particularly important
for people who want to program with defmethod instead of defun, and
hence require that defmethod supports all the features of defun. Ken
Kahn's suggestion of an alternate method-defining macro that does both
the defgeneric and the defmethod could take care of this, but it would
be nice to avoid introducing that extra special form if it isn't really
necessary.
A bad reason to prefer GFD #2 is that it is easier to implement the
discriminating function in straight Common Lisp, because methods are
always called with the same number of arguments.
If there is no reason to allow programs that can tell the difference
between GFD #1 and GFD #2, then I think we should forbid them, since
obviously this leads to confusion.
Because of supplied-p parameters, I have to back off on this. I think
we should go with GFD #1, same as Gregor leans toward.
I think we also agree that the arglists of generic functions and methods
must be consistent....
I have an anecdote that might illuminate the issue of whether two
methods for the same generic function should be allowed to have
different default-value forms for an optional argument, even when the
argument is not used for discrimination. We have a stream operation
called read-cursorpos. It takes an optional argument which is the units
in which the position is to be measured (pixels or characters). The
default value for that argument is supposed to be pixels, but one or two
of the methods defaulted it to characters instead. This caused bugs,
especially when streams are nested and one stream applies read-cursorpos
to another stream. Because Flavors only requires that methods have
consistent numbers of arguments, and doesn't check consistency of
default-value forms, these bugs had to be found the hard way. I tried
to think of an example where the freedom to have different default values
for an optional argument in different methods would be useful, but
could not come up with one.
Here is a proposed precise definition for arglist consistency. It's a
bit longwinded, but I found that was necessary to make it precise and
cover all the cases. Comments and amendments are invited. Terminology
follows CLtL p.60.
The lambda-lists of all methods for a given generic function must be
consistent with each other and with the lambda-list in the defgeneric
[if defgeneric is optional, add "if present"]. Attempting to define a
method with an inconsistent lambda-list signals an error; a program
development environment might offer to modify the conflicting
lambda-lists to make them all consistent.
To compare two lambda-lists for consistency, use the following rules:
(1) The numbers of required parameters must be equal.
(2) The numbers of optional parameters must be equal. In addition, the
initforms for corresponding optional parameters must be equal (using the
Lisp function EQUAL); an omitted initform is the same as NIL.
(3) If one lambda-list contains &rest or &key, so must the other
lambda-list. It is valid for one lambda-list to have &rest and the
other to have &key.
(4) If both lambda-lists contain &key, the sets of keywords must be the
same, except that it is valid for a keyword to appear only in one
lambda-list if the other lambda-list contains &allow-other-keys.
(5) Keyword parameters with equal keywords that appear in both
lambda-lists must have equal initforms (using the Lisp function EQUAL);
an omitted initform is the same as NIL.
(6) Keyword parameters of a method, whose keywords are not among the
generic function's keyword parameters' keywords, cannot be type
qualified (i.e. cannot be used for discrimination).
(7) If an initform that appears in both lambda-lists references an
earlier parameter, that parameter must have the same name in both
lambda-lists and in the case of keyword parameters the parameter
specifiers must appear in the same order. This ensures that variable
names in initforms have the same meaning everywhere the initform
appears. [If defmethod is allowed inside a non-top-level lexical
context, add appropriate additional language about captured free
variables.]
(8) Ignore &aux and everything after it.
Note that parameter names, type qualifiers, and the names and presence
of supplied-p parameters have no effect on lambda-list consistency.
Lambda-list consistency in more abstract terms is: the minimum number of
arguments must be equal; the maximum number of arguments must be equal;
default values for optional and keyword parameters must be consistent;
the set of keyword parameter keywords must be consistent; the defgeneric
must contain all argument-defaulting information required for
discrimination.
These rules are stricter than necessary in the sense that initforms are
compared with EQUAL, rather than a predicate that determines whether the
result of evaluating them would be EQUAL. Thus "foo" and (quote "foo")
would not be considered consistent initforms. Furthermore, if an
initform references a parameter earlier in the lambda-list, the name of
the parameter matters. I don't think the stricter rules hurt anything,
and they are simpler to explain than the minimal rules would be.
∂16-Sep-86 0626 Owners-CommonLoopsCore↑.PA@Xerox.COM Proposed Goals (Statement for OOPSLA)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 16 Sep 86 06:26:24 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 16 SEP 86 06:24:50 PDT
Return-Path: <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 16 SEP 86 06:24:34 PDT
Received: from JUNCO.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 104483; Tue
16-Sep-86 09:16:58 EDT
Date: Tue, 16 Sep 86 09:16 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Proposed Goals (Statement for OOPSLA)
To: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860916091654.1.SKEENE@JUNCO.SCRC.Symbolics.COM>
I think it's important for us to start thinking about OOPSLA in regards to
this standardization effort. It would be best to pass out something
written, because that way we can all agree before-hand on the written
statement, and after the meeting there won't be any confusion about what
was said.
I've put together a draft statement that could either stand alone, or be
the preface to some more specific documentation (if we have that in time).
Please let me know what you think about this Statement, and also your
thoughts on any other documentation that we could prepare (and get
consensus on) in time for the conference.
--------------------------------------------------------------
TOWARD A COMMON LISP STANDARD FOR OBJECT-ORIENTED PROGRAMMING
This brief paper summarizes the work that is now going on toward defining a
new Common Lisp standard for object-oriented programming.
HISTORY AND MOTIVATION
Many people in the Common Lisp community see a need for defining a standard
for object-oriented programming that would be part of Common Lisp. The
primary benefit of such a standard would be the ability to write portable
Common Lisp code in an object-oriented style.
At the Common Lisp committee meeting in Boston in December 1985, many
vendors of application software made it clear how important such a standard
is to them. Again at the ACM Lisp Conference in Cambridge in August 1986,
the same point was made.
After the ACM Lisp Conference, there was a meeting of the Common Lisp
Object-oriented Programming Committee. A clear consensus was reached that
we should begin work immediately to define a standard. Representatives
from Xerox, Lucid, Symbolics, LMI, HP, Sun, and the Japanese CommonLisp
committee supported this consensus.
A working group composed of representatives from Xerox and Symbolics met
after the ACM Lisp Conference. At that meeting we reached agreement on
several general goals.
In brief, the standard will be based on the meta-object framework of
CommonLoops, which allows experimentation with different philosophies of
object-oriented programming. The standard will also take advantage of the
years of experience of Flavors, and include Flavors features such as
declarative method combination. The standard will not be CommonLoops, nor
will it be Flavors; however it will incorporate the most useful features
from both.
PROGRESS IN AUGUST AND SEPTEMBER
During August and September, representatives from Xerox, Symbolics, and
Lucid began work on a draft specification of the standard. We started with
the basic programmer interface for defining new classes and writing methods
and generic functions. This work is ongoing, but it has not yet reached a
state where documentation is available. [We hope that this sentence turns
out to be false, but for the moment it is true.]
GOALS FOR THE STANDARD
Some high-level goals were stated and agreed-upon:
Sound basis The standard will include the aspects of object-oriented
programming that are well-understood at this time. The
standard will omit ideas that are still subjects for
research.
Flexibility The meta-object protocol of the standard will offer a
flexible framework for other designers to implement
different schemes. This encourages exploration of
different styles of object-oriented programming.
Power The standard will offer the basic tools for writing
programs in an object-oriented style, and will be powerful
enough that it meets the needs of most programs. It should
not be necessary for programmers to extend the system to do
straightforward object-oriented programming.
Simplicity The standard will specify just the language, not the
programming tools and interactive development environment.
Compatibility It should be a convenient and simple procedure to translate
programs written in CommonLoops or Flavors to the new
standard. We intend to provide tools that will perform the
translation automatically.
Implementation The standard will allow efficient implementation on stock
hardware as well as specialized machines.
FEATURES TO BE INCLUDED IN THE STANDARD
We are planning on including the following features. This is not an
exhaustive list, but is intended to communicate some of the areas of
agreement that have been reached.
Generic functions
The standard will use the normal Lisp function-calling
syntax.
Class and Type Space Merging
Every object in the Lisp system has a class and hence can
be used to select methods.
Dispatching The standard will allow for several types of dispatching,
including classical methods (which dispatch on a single
object) and multi-methods (which dispatch on more than one
object).
Multiple inheritance
Modules of behavior can be combined together freely; they
need not fit into a rigid hierarchy.
Meta-objects The standard defines objects for the major implementation
entities of the system to allow for extensibility.
Classes, methods, and generic functions all have
corresponding objects, organized by well-defined,
documented protocols.
Declarative Method Combination
Method selection and combination are controlled
declaratively, making it easier to construct programs from
a collection of modules. Users can easily define new
method combination paradigms.
FUTURE PLANS
The working group intends to develop a draft specification for the
standard. We will continue to involve the community in the feedback
process.
We will produce a portable implementation by evolving Portable Common Loops
to track the new specification. The portable implementation will enable
the community to experiment with the ideas, gain a deeper understanding of
the ideas than is possible with only a specification, and ensure that the
new object-oriented programming language receives adequate real-life
testing before its adoption as a standard.
/sub
gregor.pa@xerox,bobrow.pa@xerox
My Version of Sonya's Blurb
I spent 10 minutes revising Sonya's note - hers turned out to be
fairly good. I've laid the groundwork to call the thing CommonLoops,
but I've spiced the description with some amount of flavor.
-rpg-
ps. Oh yeah, here it is:
TOWARD A COMMON LISP STANDARD FOR OBJECT-ORIENTED PROGRAMMING
This brief paper summarizes the work that is now going on toward defining a
new Common Lisp standard for object-oriented programming.
HISTORY AND MOTIVATION
There is currently substantial experience with object-oriented
programming paradigms within a variety of contexts. The two groups
have have the most experience in this area are Symbolics and Xerox.
Flavors, an important object-oriented programming extension to Lisp,
has been in use for more than 5 years. Over that period many valuable lessons
have been learned about object-oriented programming in Lisp. In 1985,
Symbolics took these lessons to heart and designed New Flavors, which
is a compatible extension to Flavors.
Xerox has had more than 10 years of experience with object-oriented
programming, both within the Lisp tradition and within the Smalltalk
tradition. Over that period many lessons were learned, and in 1985 Xerox
began to design a new object-oriented programming extension to Common
Lisp, called CommonLoops.
In mid-1985 these two groups became aware of each other, and a significant
cross-fertilization occurred: CommonLoops absorbed some of the ideas
in New Flavors that weren't already in CommonLoops. The remarkable point,
though, was how similar these two object-oriented extensions to Lisp were.
Many people in the Common Lisp community now see a need for defining a
standard for object-oriented programming that would be part of Common
Lisp. The primary benefit of such a standard would be the ability to
write portable Common Lisp code in an object-oriented style.
At the Common Lisp committee meeting in Boston in December 1985, many
vendors of application software made it clear how important such a
standard is to them. Again at the ACM Conference on Lisp and Functional
Programming in Cambridge in August 1986, the same point was made.
After the ACM Conference there was a meeting of the Common Lisp
Object-oriented Programming Committee. A clear consensus was reached that
work should begin immediately to define a standard. Representatives
from Xerox, Lucid, Symbolics, LMI, HP, Sun, and the Japanese CommonLisp
committee supported this consensus.
A working group composed of representatives from Xerox and Symbolics met
after the ACM Conference; at the meeting this working group reached
agreement on several general goals.
In brief, the standard will be based on the meta-object framework of
CommonLoops, which allows experimentation with different philosophies of
object-oriented programming. Additional features from New Flavors will be
added to CommonLoops to flesh out the programmer interface; in particular,
a declarative method combination facility and a classical method
definition syntax patterned after those features in New Flavors will be
added to CommonLoops to create an extension to Common Lisp that represents
the best features of both systems seamlessly merged.
PROGRESS IN AUGUST AND SEPTEMBER
During August and September, representatives from Xerox, Symbolics, and
Lucid began work on a draft specification of the standard. This working
group started with the basic programmer interface for defining new classes
and writing methods and generic functions. This work is ongoing, but a
draft of the programmer interface is available - the meta-object protocol
specification will be available soon.
GOALS FOR THE STANDARD
Some high-level goals were stated and agreed-upon:
Sound basis The standard will include the aspects of object-oriented
programming that are well-understood at this time. The
standard will omit ideas that are still subjects for
research.
Flexibility The meta-object protocol of the standard will offer a
flexible framework for other designers to implement
different schemes. This encourages exploration of
different styles of object-oriented programming.
Power The standard will offer the basic tools for writing
programs in an object-oriented style, and will be powerful
enough that it meets the needs of most programs. It should
not be necessary for programmers to extend the system to do
straightforward object-oriented programming.
Simplicity The standard will specify just the language, not the
programming tools and interactive development environment.
Compatibility It should be a convenient and simple procedure to translate
programs written in CommonLoops or New Flavors to the new
standard. We intend to provide tools that will perform the
translation automatically.
Implementation The standard will allow efficient implementation on stock
hardware as well as specialized machines.
FEATURES TO BE INCLUDED IN THE STANDARD
The following features wil be included in the standard.. This is not an
exhaustive list, but is intended to communicate some of the areas of
agreement that have been reached.
Generic functions
The standard will use the normal Lisp function-calling
syntax.
Class and Type Space Merging
Every object in the Lisp system has a class and hence can
be used to select methods.
Dispatching The standard will allow for several types of dispatching,
including classical methods (which dispatch on a single
object) and multi-methods (which dispatch on more than one
object).
Multiple inheritance
Modules of behavior can be combined together freely; they
need not fit into a rigid hierarchy.
Meta-objects The standard defines objects for the major implementation
entities of the system to allow for extensibility.
Classes, methods, and generic functions all have
corresponding objects, organized by well-defined,
documented protocols.
Declarative Method Combination
Method selection and combination are controlled
declaratively, making it easier to construct programs from
a collection of modules. Users can easily define new
method combination paradigms.
FUTURE PLANS
The working group intends to develop a draft specification for the
standard. The specification process will involve the community in the
feedback process.
There will be a portable implementation based on Portable Common Loops,
which will evolve to to track the new specification. The portable
implementation will enable the community to experiment with the ideas,
gain a deeper understanding of the ideas than is possible with only a
specification, and ensure that the new object-oriented programming
language receives adequate real-life testing before its adoption as a
standard.
∂16-Sep-86 0630 Owners-commonloopscore↑.pa@Xerox.COM Re: Goals of the Specification
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 16 Sep 86 06:30:52 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 16 SEP 86 06:29:26 PDT
Return-Path: <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 16 SEP 86 06:28:46 PDT
Received: from JUNCO.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 104492; Tue
16-Sep-86 09:25:51 EDT
Date: Tue, 16 Sep 86 09:25 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Goals of the Specification
To: Masinter.pa@Xerox.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, commonloopscore↑.pa@Xerox.COM
In-Reply-To: <860915-161758-6228@Xerox>
Message-ID: <860916092549.2.SKEENE@JUNCO.SCRC.Symbolics.COM>
Date: 15 Sep 86 16:15 PDT
From: Masinter.pa@Xerox.COM
The current list contents of commonloopscore↑.pa@xerox.com is:
Bobrow.pa Common-Lisp-Class-archive@Stony-Brook.SCRC.Symbolics.COM
COMMON-LISP-OBJECT-SYSTEM@SU-AI.ARPA
CommonLoops-Spec-Archive@AI.AI.MIT.EDU DLW@QUABBIN.SCRC.Symbolics.COM
edsel!lgd@navajo.stanford.edu Gregor.pa Kahn.pa Lanning.pa
LGD@SU-AI.arpa Masinter.pa Moon@STONY-BROOK.SCRC.Symbolics.COM
SKeene@STONY-BROOK.SCRC.Symbolics.COM
I assume RPG gets the mail via COMMON-LISP-OBJECT-SYSTEM@SU-AI.ARPA,
although I don't know who else does. I'm not sure who LDG is (I assume
someone at Lucid) or SKeene@STONY-BROOK.SCRC.Symbolics.COM.
I'm a writer at Symbolics. -- Sonya Keene
I don't think I object to what I've heard of the goals, I just didn't
see the list. Avoiding obvious name conflicts with Flavors and allowing
mechanical translation of Flavors, while a bow to backward
compatibility, is not an onerous one.
∂16-Sep-86 1128 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: default optional arguments to a generic function
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 16 Sep 86 11:28:28 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 16 SEP 86 10:39:58 PDT
Redistributed: CommonLoopsCore↑.pa
Received: from Cabernet.ms by ArpaGateway.ms ; 16 SEP 86 10:38:19 PDT
Date: 16 Sep 86 10:37 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: default optional arguments to a generic function
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 15 Sep 86 23:57 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860916-103958-6836@Xerox>
GFD #1. the defaults from the defgeneric are used only for method
lookup. This is the kind I described above.
GFD #2. the defaults from the defgeneric are used for method lookup
and also passed to the method.
There is a fundamental conceptual difference. I think the notion of
supplying defaults is part of the contract between the generic function
and the world. This is an argument for GFD #1. We all seem to agree
that defmethods, if they specify optionals, must agree with the generic
function. If the EQUALS rule is used for defaults (I support this),
then I see no reason for the default forms to be evaluated twice. If
methods can have exactly the same supplied-p args as specified in the
generic function (no more, no less - just local renaming allowed) then
there is no penalty for passing supplied-p args to each method as
"required args". The calling sequence is uniform.
Given:
(defgeneric foo (x &optional y (z *v1* supplied-z)) ...)
then the following is legal
(defmethod foo ((x c1) &optional ((y c2)) (z *v1* my-supplied-z))) ..)
and the following are illegal
(defmethod foo ((x c1) &optional (y NIL supplied-y)(z *v1*
my-supplied-z))) ..)
(defmethod foo ((x c1) &optional y (z *v1* ))) ..)
One issue to be addressed is the following. If we insist on the EQUALS
rule, then if the default value form changes in the defgeneric, it must
be changed in all methods. This redundancy is bad design. To allow
arg-specification and supplied-p specification, I suggest another
keyword &optional-spec. Following &optional-spec can be
{varName|(varName arg-specifier [supplied-p-var])}*
where the interpretation is the obvious one, given in my message of last
week. The rule of supplied-p correspondence still holds, but no default
value form need be specified.
-- danny
∂16-Sep-86 1413 Gregor.pa@Xerox.COM the kinds of method lookup people claim they want
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 16 Sep 86 14:12:58 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 16 SEP 86 14:00:48 PDT
Date: Tue, 16 Sep 86 13:59 PDT
From: Gregor.pa@Xerox.COM
Subject: the kinds of method lookup people claim they want
To: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860916135909.5.GREGOR@AVALON.XEROX-PARC>
Line-fold: no
I spent lunch today listening to people talk about the kinds of method
lookup which they would like to have CommonLoops support. I was struck
by the variety of things which people claimed would be natural or
convenient or even essential. By the end of lunch I was very confused
about what we should do about discriminating on optional arguments.
In the interest of confusing the rest of you, I thought I would collect a
list of all the cases of method definition people thought they would
want. Please add any other examples or potential screw cases.
NOTE: In each of these examples I have used some syntax and some
defining forms which I intend only to express the example. Do not
regard the syntax I have used as a proposal for how we should do
anything.
Case 1a. "draw-line"
draw-line takes an optional, the width of the line in device dependent
units. Because they are device dependent units, each individual method
would like to default this argument on its own.
(defmethod draw-line ((dev printer) p1 p2 &optional (width 7))
...)
(defmethod draw-line ((dev window) p1 p2 &optional (width 1))
...)
Case 1b.
Within case 1, some methods may want to take an extra argument. Also
see case 3 which is similar.
(defmethod draw-line ((d gray-display) p1 p2
&optional (width 3)
(gray *gray1*))
..)
Case 2. "draw (GFD#2)"
The generic function takes an optional argument. For all the methods,
the optional argument should default to the same value. In addition,
method lookup should be based on the value of the optional argument
(after defaulting) and the defaulted value should be passed in. This
corresponds to what I previously called GFD#2.
(defgeneric draw (thing &optional (place *draw-window*))
"Draw thing on place.")
(defmethod draw ((thing line) (place raster-display)) ...)
(defmethod draw ((thing line) (place vector-display)) ...)
People have also said that within the individual methods they would like
to have access to the supplied-p information for the optional argument.
Case 3. "move"
A generic function (e.g. move) has only classical methods. Some of the
methods want to accept more arguments than others. For example: move
when then first argument is a block takes a position to move to, but
move when the first argument is a rabbit takes no extra arguments (the
rabbit will jump up and down).
(defmethod move ((b block) to-x to-y) ..)
(defmethod move ((r rabbit)) ..)
Case 4. "Guy's proposal"
In this porposal, method lookup checks argument specifiers for only the
supplied arguments. When there are two arguments supplied, the most
specific of the two argument methods is called.
(defmethod foo (a b &optional (c x) (d y)) body)
is simply an abbreviation for
(defmethod foo (a b) (let ((c x) (d y)) body))
(defmethod foo (a b c) (let ((d y)) body))
(defmethod foo (a b c d) body)
So that:
(defmethod gls ((a boat) &optional ((p plane) *default*)) ..)
(defmethod gls ((a speed-boat)) ...)
(foo <a speed-boat>) ;runs method 2
(foo <a speed-boat> <a plane>) ;runs method 1
-------
∂16-Sep-86 1841 Owners-CommonLoopsCore↑.pa@Xerox.COM run-super
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 16 Sep 86 18:41:07 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 16 SEP 86 16:24:56 PDT
Return-Path: <Moon@ELEPHANT-BUTTE.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from ELEPHANT-BUTTE.SCRC.Symbolics.COM ([192.10.41.41]) by
Xerox.COM ; 16 SEP 86 16:23:57 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ELEPHANT-BUTTE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 81031;
Tue 16-Sep-86 17:10:40 EDT
Date: Tue, 16 Sep 86 17:10 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: run-super
To: CommonLoopsCore↑.pa@Xerox.COM
References: <860905004612.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <860916171027.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
The referenced message, from 5 September, contains two implementations
of RUN-SUPER in Flavors. This message contains a third implementation
that eliminates some problems with the other two implementations, which
were discussed in that message. All three of these implementations have
been tested and work. To simply things, I removed :AROUND methods from
this version, but it would only take a few lines of code to put them
back in if we wished to do so.
I see no reason why this couldn't be the default method-combination type
in Common Lisp Classes. Compilation will be a little slower than in
Flavors, but not much slower, and code that doesn't use run-super will
not pay any efficiency cost, while code that does use run-super will be
quite efficient.
Of course this exact implementation could not be used, because it uses
Flavors interfaces in place of meta-object protocols, uses Symbolics'
code-walker rather than one that can be assumed to be present in every
implementation, and contains machine-dependencies, especially connected
with the way method dispatching works in our system. That's not
important, the important thing is the semantics of how RUN-SUPER and
method-combination fit together, which is:
all the :BEFORE methods are executed, most-specific first
the most specific primary method is executed, and supplies the
value(s)
if it uses RUN-SUPER, that calls the next primary method, and so on
if RUN-SUPER exhausts the supply of primary methods, it signals an
error
all the :AFTER methods are executed, least-specific first
Shall we make this the default method-combination type, or does anyone
object? (Myself, I object to the name RUN-SUPER, and maybe we can think
of a more expressive name. If not, I can live with that one.)
Most of the hair in this code is connected with optimizations so that if
run-super is not used, the compiled code is exactly the same as in
Flavors
:daemon method-combination (no extra overhead for run-super).
;;;; Dynamically plus lexically scoped version, avoids problems of both
the above.
;;;; This scheme uses more machine-dependencies to avoid an extra level
of
;;;; lambda in the continuations.
;;;; I removed :AROUND methods but they could easily be added back in.
;;; List of alternating methods and self-mapping-tables, used by
RUN-SUPER
(DEFVAR *SUPERCLASS-CONTINUATIONS*)
;;; Shadowed by a MACROLET
(DEFUN RUN-SUPER ()
(ERROR "RUN-SUPER not called from a proper lexical environment.
RUN-SUPER is only valid in a primary method with :SUPER-DAEMON
method-combination."))
;;; Appears at the tail of *SUPERCLASS-CONTINUATIONS*
;;; Change this to a function that just returns NIL if you prefer that
semantics
(DEFUN RUN-SUPER-EXHAUSTED (&REST IGNORE)
(ERROR "RUN-SUPER called from the least specific method; no more
methods are available."))
(DEFINE-METHOD-COMBINATION :SUPER-DAEMON ()
((BEFORE "before" :EVERY :MOST-SPECIFIC-FIRST (:BEFORE))
(PRIMARY "primary" :EVERY :MOST-SPECIFIC-FIRST () :DEFAULT)
(AFTER "after" :EVERY :MOST-SPECIFIC-LAST (:AFTER)))
(:METHOD-TRANSFORMER
;; Deal with run-super by transforming the method's arglist and
body
(:METHOD-ARGLIST
(MULTIPLE-VALUE-SETQ (METHOD-ARGLIST METHOD-BODY)
(TRANSFORM-SUPER-DAEMON-METHOD FUNCTION-SPEC METHOD-ARGLIST
METHOD-BODY)))
(:METHOD-BODY METHOD-BODY))
;; Remove from dependencies the primary methods that cannot be reached
by RUN-SUPER
(SETQ PRIMARY (LOOP FOR METHOD IN PRIMARY
COLLECT METHOD
WHILE (METHOD-USES-RUN-SUPER METHOD)))
;; Return appropriate method combining form
`(MULTIPLE-VALUE-PROG2
,(CALL-COMPONENT-METHODS BEFORE)
,(COND ((NULL PRIMARY) `NIL)
((AND (NULL (REST PRIMARY))
(NOT (METHOD-USES-RUN-SUPER (FIRST PRIMARY))))
(CALL-COMPONENT-METHOD (FIRST PRIMARY))) ;Optimize single-method
case
(T
;; Stash the machine-dependent information needed for run-super,
;; then call the first primary method, which will call the rest of
them.
`(STACK-LET ((*SUPERCLASS-CONTINUATIONS*
(LIST ,@(LOOP FOR METHOD IN (REST PRIMARY)
COLLECT `(FUNCTION ,METHOD)
COLLECT `(GET-FLAVOR-MAPPING-TABLE-FOR-INSTANCE
SELF ',(METHOD-FLAVOR METHOD)))
#'RUN-SUPER-EXHAUSTED)))
,(CALL-COMPONENT-METHOD (FIRST PRIMARY)))))
,(CALL-COMPONENT-METHODS AFTER)))
;;; Determine whether this method needs a binding of
*SUPERCLASS-CONTINUATIONS*
;;; This works by calling a machine-dependent facility
(DEFUN METHOD-USES-RUN-SUPER (FUNCTION-SPEC)
(MULTIPLE-VALUE-BIND (VALUE FOUND)
(COMPILER:FILE-DECLARATION FUNCTION-SPEC 'USES-RUN-SUPER)
(IF FOUND VALUE (SI:FUNCTION-SPEC-GET FUNCTION-SPEC
'USES-RUN-SUPER))))
;;; Arrange for NOTE-WHETHER-METHOD-USES-RUN-SUPER to be called when
this method
;;; is defined, via the USES-RUN-SUPER declaration. It would be better
to do this
;;; with meta-object protocols, when we have them.
(PUSHNEW '(USES-RUN-SUPER ADD-NOTE-WHETHER-METHOD-USES-RUN-SUPER)
*DEFMETHOD-DECLARATIONS* :TEST #'EQUAL)
(DEFUN ADD-NOTE-WHETHER-METHOD-USES-RUN-SUPER (FUNCTION-SPEC DECLARATION
IGNORE)
`((NOTE-WHETHER-METHOD-USES-RUN-SUPER ',FUNCTION-SPEC ',(SECOND
DECLARATION))))
;;; Called when a primary method with :SUPER-DAEMON method combination
is defined
(DEFUN NOTE-WHETHER-METHOD-USES-RUN-SUPER (FUNCTION-SPEC USES-RUN-SUPER)
(LET ((CHANGED (AND (FDEFINEDP FUNCTION-SPEC)
(NOT (EQ (SI:FUNCTION-SPEC-GET FUNCTION-SPEC 'USES-RUN-SUPER)
USES-RUN-SUPER)))))
;; Record the information where METHOD-USES-RUN-SUPER can find it.
(IF USES-RUN-SUPER
(SI:FUNCTION-SPEC-PUTPROP FUNCTION-SPEC T 'USES-RUN-SUPER)
(SI:FUNCTION-SPEC-REMPROP FUNCTION-SPEC 'USES-RUN-SUPER))
;; If combined methods have to call a different set of primary
methods now, update them.
(WHEN CHANGED
(RECOMPILE-FLAVOR (METHOD-FLAVOR FUNCTION-SPEC)
:GENERIC (METHOD-GENERIC FUNCTION-SPEC)
:IGNORE-EXISTING-METHODS T))))
;;; Expand any RUN-SUPER in the body of this method into the appropriate
code
;;; to call the next method on the continuation list and rebind that
list to its tail.
;;; This works by calling some machine-dependent facilities.
(DEFUN TRANSFORM-SUPER-DAEMON-METHOD (FUNCTION-SPEC METHOD-ARGLIST
METHOD-BODY)
(DECLARE (VALUES METHOD-ARGLIST METHOD-BODY))
;; This is for primary methods only
(UNLESS (OR (NULL (METHOD-OPTIONS FUNCTION-SPEC))
(EQUAL (METHOD-OPTIONS FUNCTION-SPEC) '(:DEFAULT)))
(RETURN-FROM TRANSFORM-SUPER-DAEMON-METHOD (VALUES METHOD-ARGLIST
METHOD-BODY)))
;; Check whether the method actually uses RUN-SUPER
(MULTIPLE-VALUE-BIND (DECLARATIONS BODY)
(SI:FIND-BODY-DECLARATIONS METHOD-BODY NIL)
(COND ((LT:MAPFORMS (LAMBDA (SUBFORM KIND USAGE RUN-SUPER-USED)
(IGNORE USAGE)
(COND (RUN-SUPER-USED
(VALUES T T)) ;No need to look any further
((AND (LISTP KIND) (EQUAL SUBFORM '(RUN-SUPER)))
(VALUES T T)) ;RUN-SUPER called as a function
(T (VALUES NIL NIL)))) ;else keep looking
(CONS 'PROGN BODY))
;; This method contains a call to RUN-SUPER.
;; Record that for the benefit of METHOD-USES-RUN-SUPER.
(WHEN COMPILER:UNDO-DECLARATIONS-FLAG
(COMPILER:FILE-DECLARE FUNCTION-SPEC 'USES-RUN-SUPER T))
;; Adjust the arglist so we can pass the arguments on to the next
method.
(MULTIPLE-VALUE-BIND (ARGUMENTS APPLY NEW-METHOD-ARGLIST)
(LT:LAMBDA-LIST-ARGUMENTS METHOD-ARGLIST)
(VALUES
NEW-METHOD-ARGLIST
;; Make the body copy the continuations from the special
variable
;; into a lexical variable so that it gets scoped properly if
this method
;; contains RUN-SUPER inside a LAMBDA, and so that if RUN-SUPER
is done
;; twice the same method gets called each time, and put a
MACROLET
;; of RUN-SUPER around the body.
`(,@DECLARATIONS
(DECLARE (USES-RUN-SUPER T))
(LET ((.SUPERCLASS-CONTINUATIONS. *SUPERCLASS-CONTINUATIONS*))
(MACROLET
((RUN-SUPER ()
`(LET ((*SUPERCLASS-CONTINUATIONS* .SUPERCLASS-CONTINUATIONS.))
;; Machine-dependent call similar to CALL-COMPONENT-METHOD
(,',(IF APPLY 'APPLY 'FUNCALL)
(POP *SUPERCLASS-CONTINUATIONS*) ;Method
SELF
(POP *SUPERCLASS-CONTINUATIONS*) ;Mapping-table
.GENERIC.
,',@ARGUMENTS))))
,@BODY))))))
(T
;; Ordinary method that doesn't use RUN-SUPER. Record that fact for
;; the benefit of METHOD-USES-RUN-SUPER, and return original arglist
and body
;; with a declaration added saying it doesn't use run-super.
(WHEN COMPILER:UNDO-DECLARATIONS-FLAG
(COMPILER:FILE-DECLARE FUNCTION-SPEC 'USES-RUN-SUPER NIL))
(VALUES METHOD-ARGLIST
`(,@DECLARATIONS
(DECLARE (USES-RUN-SUPER NIL))
,@BODY))))))
(DEFGENERIC SDTEST (X Y)
(:METHOD-COMBINATION :SUPER-DAEMON))
(DEFFLAVOR SDTEST1 () ())
(DEFFLAVOR SDTEST2 () (SDTEST1))
(DEFFLAVOR SDTEST3 () (SDTEST2))
(DEFMETHOD (SDTEST SDTEST1) (X)
(LIST 1 X))
(DEFMETHOD (SDTEST SDTEST2) (X)
(CONS 2 (RUN-SUPER)))
(DEFMETHOD (SDTEST SDTEST3) (X)
(CONS 3 (RUN-SUPER)))
(SDTEST (MAKE-INSTANCE 'SDTEST3) 105)
; => (3 2 1 105)
∂16-Sep-86 1841 Owners-CommonLoopsCore↑.PA@Xerox.COM What we should agree on before OOPSLA
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 16 Sep 86 18:41:19 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 16 SEP 86 17:51:41 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 16 SEP 86 17:51:14 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 105361; Tue
16-Sep-86 20:48:21 EDT
Date: Tue, 16 Sep 86 20:50 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: What we should agree on before OOPSLA
To: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860916205006.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Here is what I would like us to try to agree on, in time to write it up
and distribute it to whoever is interested at OOPSLA. I have pared this
list down to what I think is possible if we focus on this. I think it's
important to come up with something real, if we take seriously the
promise we made to the community in August.
- A statement of the goals and general character of this project. This
could be based on what SKeene mailed out this morning (Tuesday), with
modifications resulting from other people's review of it.
- The syntax of the most basic language facilities, with very brief
discussions of their semantics and a statement that additional
facilities are still being discussed. See proposed list below.
- A statement that meta-object protocols will exist and be precisely
defined, but currently they are not ready to go into the document
(assuming there isn't enough time left for this).
Basic language facilities that I think we can agree on by the end of
next week:
DEFCLASS
overall syntax
some of the options
some or all of the slot-options
class precedence rules
DEFGENERIC
overall syntax
some or all of the options
setf syntax
DEFMETHOD
"general" syntax, with space left for "classical" syntax
discrimination on required arguments
discrimination by classes
setf syntax
WITH
the only problem here is the name, which is too short
MAKE-INSTANCE
interface seen by the caller
we may have to defer the protocol for initialization methods
CLASS-OF
PRINT-OBJECT
DESCRIBE-OBJECT (can we name this DESCRIBE?)
DEFINE-METHOD-COMBINATION
we may have to postpone the details of this if we
have trouble agreeing
This leaves out a great deal, but should be enough to give people
a good idea of what is coming. At this point I think we should
leave out anything that we are having trouble converging on and
deal with it later. There will be a face to face meeting after
OOPSLA.
I'd like some feedback on this!
∂17-Sep-86 0856 Bobrow.pa@Xerox.COM Re: run-super
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 08:56:34 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 17 SEP 86 08:28:14 PDT
Date: 17 Sep 86 08:29 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: run-super
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 16 Sep 86 17:10 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860917-082814-7626@Xerox>
To simplify things, I removed :AROUND methods from this version, but
it would only take a few lines of code to put them back in if we wished
to do so.
I would like to see the addition for :around. (What do you think
changing ":around" to ":full-shadow"?) The particular feature I am interested
in is how you express the transformation of a form to a method. Is
this what your were referring to in:
;;;; This scheme uses more machine-dependencies to avoid
;;;; an extra level of lambda in the continuations.
That is, would you please fix up the following rough form of
the body of whopper-super-daemon combination.
What would it look like in Common Lisp? Thanks.
(STACK-LET ((*SUPERCLASS-CONTINUATIONS*
(LIST ,@(LOOP FOR METHOD IN (REST AROUND)
COLLECT `(FUNCTION ,METHOD)
COLLECT `(GET-FLAVOR-MAPPING-TABLE-FOR-INSTANCE
SELF ',(METHOD-FLAVOR METHOD)))
(make-method-from-form `(MULTIPLE-VALUE-PROG2 ...))
;;; the (MULTIPLE-VALUE-PROG2 ...) is the body found in the referenced message.
;;; this last form transforms that expression appropriately
)))
,(CALL-COMPONENT-METHOD (FIRST AROUND)))))
---
The important thing is the semantics of how RUN-SUPER and
method-combination fit together, which is:
all the :BEFORE methods are executed, most-specific first the
most specific primary method is executed, and supplies the value(s)
if it uses RUN-SUPER, that calls the next primary method,
and so on if RUN-SUPER exhausts the supply of primary methods, it
signals an error
all the :AFTER methods are executed, least-specific first
Shall we make this the default method-combination type, or does
anyone object? (Myself, I object to the name RUN-SUPER, and maybe we
can think of a more expressive name. If not, I can live with that one.)
I am happy with this as the default. I have no better name than run-super.
run-continuation is not semantically correct, and super has a history people
can relate to. I don't like the name "super-daemon" or even "daemon",
although history rgues for each of those. How about "simple-nested". or just
"nested" sincer the primary is nested in befores and afters, and run-super
does dynamically controlled nesting.
I would want to describe super-daemon in the spec in pieces.
The first would describe the specifcation of run-super alone as in Loops. Then
I would describe standar declarative method combination, and the interaction.
Finally, I would want to describe the method combination language that allows
these to be defined.
∂17-Sep-86 1036 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: default optional arguments to a generic function
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 10:36:19 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 17 SEP 86 09:24:58 PDT
Redistributed: CommonLoopsCore↑.pa
Received: from Cabernet.ms by ArpaGateway.ms ; 17 SEP 86 09:24:43 PDT
Date: 17 Sep 86 09:21 PDT
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: default optional arguments to a generic function
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 15 Sep 86 23:57 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860917-092458-7674@Xerox>
Unfortunately, the most important typo in my GFD#1 and GFD#2 message is
that I said I was leaning towards GFD#1. In fact, I lean towards #2.
GFD #1. the defaults from the defgeneric are used only for method
lookup. This is the kind I described above.
GFD #2. the defaults from the defgeneric are used for method lookup
and also passed to the method.
Doesn't your anecdote, which provides a good example of why two methods
should not be allowed to have different default value forms also support
GFD#2?
Date: Mon, 15 Sep 86 23:57 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Because of supplied-p parameters, I have to back off on this.
Supplied-p parameters are what confuse me too. Let me recap my thinking
on this.
I think of the arguments that the generic function accepts as being part
of its contract with the world. I think of any argument defaulting done
on those arguments as being part of that same contract (I lean towards
GFD#2).
But supplied-p information doesn't have anything to do with the
generic's contract with the world. Instead, supplied-p information
seems to me to be part of the generic functions contract with its
methods.
For me, the question about supplied-p arguments comes down to deciding
if these two contracts (generic---world, generic---methods) are the
*same*. In other words, the lambda list which appears in the defgeneric
clearly specifies the generic-world contract, the question is to what
extent does it also specify the generic-methods contract.
If we make the defgeneric completely specify both contracts, then the
defgeneric must say which arguments the methods can (and must) get
supplied-p information for.
If the defgeneric does not specify which arguments supplied-p
information is available for, but rather methods can ask for this
information on a per-method basis, I get confused.
To compare two lambda-lists for consistency, use the following
rules:
I want to try to re-write these rules to get rid of this EQUAL rule
about optional argument default value forms. In order to do that, I am
going to ignore the issue of supplied-p arguments (by not allowing
methods to get their hands on that information), and I am going to
assume that defgenerics are required. Note that my rules compare
defgeneric lambda lists to defmethod lambda lists.
1. The method must accept as required arguments the sum of the generic's
required optional and rest arguments.
2. &optional may not appear in a defmethod lambda list (an extension
would
allow this in the case where the defgeneric lambda list has neither
&key
nor &rest).
3. The method must accept the same keywords as the generic;
OR it can accept a subset of the ones in the defgeneric if it has
&allow-other-keys;
OR it can accept a superset of the ones in the defgeneric if the
defgeneric has &allow-other-keys.
4. &aux is not allowed in defgenerics, it is allowed in defmethods with
the
usual meaning.
Here are some examples:
(defgeneric draw (thing &optional (place *drawing-place*)))
(defmethod draw ((thing box) (place window)) ...)
(defmethod draw ((thing box) (place printer)) ...)
(defgeneric save (file &rest things))
(defmethod save ((file fancy-file) things) ...)
(defgeneric shape (thing &optional &key width height &allow-other-keys))
(defmethod shape ((r rectangle) &key width height) ...)
(defmethod shape ((c circle) &key radius) ...)
I another message, I will send a minimal proposal about defmethod
arguments which I think provides all the functionality we really
understand, and could be extended to any optional argument scheme we
eventually work out. If, by friday, we have settled on a scheme that
works for optional arguments I suggest we put this minimal proposal in
the spec to take to DC and OOPSLA.
∂17-Sep-86 1037 Kahn.pa@Xerox.COM Re: run-super
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 10:36:52 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 17 SEP 86 09:30:11 PDT
Date: 17 Sep 86 09:29 PDT
Sender: Kahn.pa@Xerox.COM
Subject: Re: run-super
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 16 Sep 86 17:10 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
From: Kahn.pa@Xerox.COM, Bobrow.pa@Xerox.COM
Message-ID: <860917-093011-7680@Xerox>
Regarding your code
(DEFINE-METHOD-COMBINATION :SUPER-DAEMON ()
...
;; Remove from dependencies the primary methods that cannot be reached
by RUN-SUPER
(SETQ PRIMARY (LOOP FOR METHOD IN PRIMARY
COLLECT METHOD
WHILE (METHOD-USES-RUN-SUPER METHOD)))
;; Return appropriate method combining form
...)
The last method in the primary list should be the first one that does
not use run-super. Only if all primary methods use run-super,
#'RUN-SUPER-EXHAUSTED must be inserted at the end of the list. It is
not an error for all primary methods to call run-super since in some
contexts the last primary method may be in another position in the
*SUPERCLASS-CONTINUATIONS* list. We might also then define run-super?
that returns NIL if the next continuation is #'RUN-SUPER-EXHAUSTED.
----- ken and danny
∂17-Sep-86 1037 Kahn.pa@Xerox.COM DEFCLASS should replace DEFSTRUCT
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 10:37:05 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 17 SEP 86 10:14:41 PDT
Date: 17 Sep 86 10:14 PDT
Sender: Kahn.pa@Xerox.COM
Subject: DEFCLASS should replace DEFSTRUCT
To: CommonLoopsCore↑.pa@Xerox.COM
cc: Kahn.pa@Xerox.COM
From: Ken Kahn <Kahn.pa@Xerox.COM>
Message-ID: <860917-101441-7733@Xerox>
A few months ago we believed that CommonLoops could just extend
DEFSTRUCT to deal with multiple inheritance and metaclasses. Then there
was this idea that DEFSTRUCT did some things poorly and we could do them
better in DEFCLASS. I am willing to agree to this if the spec proposes
that we flush DEFSTRUCT from Common Lisp and provide a DEFSTRUCT macro
for backwards compatibility that is mostly implemented in CommonLoops.
Why should anyone use DEFSTRUCT anymore? CommonLoops can provide a
STRUCTURE-CLASS metaclass that provides the same performance/capability
trade-offs as current DEFSTRUCT. The :TYPE option is weird but it could
still be supported, so that instances and "structures" built out of
lists and vectors can be made and accessed in a uniform manner
(MAKE-INSTANCE, GET-SLOT...). CLASS-OF won't work on them so one can't
put methods on them but that's the case in any case. 16 pages of the
Silver Book could go away if DEFSTRUCT is flushed. It would be a shame
if Common Lisp had to have two ways of defining structured objects, one
of which subsumes the other.
In Sonya's message about goals she states:
Simplicity The standard will specify just the language, not the
programming tools and interactive development
environment.
I think a more important aspect of Simplicity is that the language
specified not be unduely complex. Adding DEFCLASS and not removing
DEFSTRUCT clearly does add unneccessary complexity.
----- ken
∂17-Sep-86 1632 Gregor.pa@Xerox.COM Re: What we should agree on before OOPSLA
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 16:31:52 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 17 SEP 86 11:51:57 PDT
Date: 17 Sep 86 11:47 PDT
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: What we should agree on before OOPSLA
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 16 Sep 86 20:50 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860917-115157-7842@Xerox>
This list looks pretty good to me.
I believe that Sonya's message is a good start for Part 1. I know that
we have some small changes we want to make to it. These will be in a
separate message.
I believe that the spec we are working on will satisfy Part 2, once we
work out the basic language facilities to be covered. I agree that we
can work out all the basic language details you included at the end of
your message. In addition, we may be able to come to some agreement on
optional arguments, I am not quite ready to quit on this.
You may be right that we should not include what we have so far for
meta-object protocols. You are certainly right that we don't have time
to tighten this up.
As I said yesterday, I hope to FEDx a spec to you by the end of the day
today.
In addition, I will try to send messages giving our current status for:
some defclass options which are unresolved,
with
describe-object
define-method-combination
I think these (except define-method-combination) should be easy to
resolve and can they be put in the spec easily.
∂17-Sep-86 1636 Gregor.pa@Xerox.COM The name of WITH
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 16:32:04 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 17 SEP 86 13:12:52 PDT
Date: 17 Sep 86 13:12 PDT
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: The name of WITH
To: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860917-131252-7924@Xerox>
If people really think the name WITH is too short, then the name
WITH-SLOTS seems like the obvious best name to me.
∂17-Sep-86 1637 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: Getting together to work
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 16:33:14 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 17 SEP 86 14:54:07 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 17 SEP 86 14:53:56 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 106466; Wed
17-Sep-86 17:41:42 EDT
Date: Wed, 17 Sep 86 17:41 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Getting together to work
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860914-111121-5339@Xerox>
Message-ID: <860917174139.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 14 Sep 86 11:11 PDT
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
....
The conclusion, after various discussions, is that Sonya Keene, Dave
Moon, and Dan Weinreb will be in Palo Alto from Thursday October 2
through Sunday October 5. Exact times to be figured out later, but
basically all of Friday and Saturday will be available, possibly late
Thursday, and probably none of Sunday. I'll send mail with exact times
when we know the flight times.
This what Gregor proposed originally. I would have liked to have met
before OOPSLA instead, but it proved to be impossible. I assume we'll
have intense working sessions on the details of the standard for these
two days, with people from Lucid, Symbolics, and Xerox. Gregor, you're
going to arrange a meeting room and make sure people show up and stuff
like that, right?
∂17-Sep-86 1636 Bobrow.pa@Xerox.COM Proposed Goals (Statement for OOPSLA)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 16:32:14 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 17 SEP 86 11:32:16 PDT
Date: 17 Sep 86 11:33 PDT
From: Bobrow.pa@Xerox.COM
Subject: Proposed Goals (Statement for OOPSLA)
To: CommonLoopsCore↑.pa@Xerox.COM
cc: Bobrow.pa@Xerox.COM
Message-ID: <860917-113216-7821@Xerox>
Dick edited Sonya's version, then Danny and Gregor edited his to produce
this.
TOWARD A COMMON LISP STANDARD FOR OBJECT-ORIENTED PROGRAMMING
This brief paper summarizes the work that is now going on toward defining
a new Common Lisp standard for object-oriented programming.
HISTORY AND MOTIVATION
There is currently substantial experience with object-oriented programming
paradigms within a variety of contexts. The two groups have have the most
experience in this area are Symbolics and Xerox.
Flavors, an important object-oriented programming extension to Lisp, has
been in use for more than 7 years. Over that period many valuable lessons
have been learned about object-oriented programming in Lisp. In 1985,
Symbolics took these lessons to heart and designed New Flavors, which is a
compatible extension to Flavors.
Xerox has had more than 10 years of experience with object-oriented
programming, both within the Lisp tradition and within the Smalltalk
tradition. Over that period many lessons were learned, and in 1985 Xerox
began to design a new object-oriented programming extension to Common
Lisp, called CommonLoops.
In mid-1985 these two groups became aware of each other. These two
object-oriented extensions to Lisp had important similarities.
CommonLoops evolved to include some of the ideas in new Flavors.
Many people in the Common Lisp community now see a need for defining a
standard for object-oriented programming that would be part of Common
Lisp. The primary benefit of such a standard would be the ability to
write portable Common Lisp code in an object-oriented style.
At the Common Lisp committee meeting in Boston in December 1985, many
vendors of application software made it clear how important such a
standard is to them. Again at the ACM Conference on Lisp and Functional
Programming in Cambridge in August 1986, the same point was made.
After the ACM Conference there was a meeting of the Common Lisp
Object-oriented Programming Committee. A clear consensus was reached that
work should begin immediately to define a standard. Representatives from
Xerox, Lucid, Symbolics, LMI, HP, Sun, and the Japanese CommonLisp
committee supported this consensus.
A working group composed of representatives from Xerox and Symbolics met
after the ACM Conference; at the meeting this working group reached
agreement on several general goals.
In brief, the standard will be based on the meta-object framework of
CommonLoops, which allows experimentation with different philosophies of
object-oriented programming. Additional features from new Flavors will be
added to CommonLoops to flesh out the programmer interface; in particular,
a declarative method combination facility patterned after that in new
Flavors has been added to CommonLoops to create an extension to Common
Lisp that represents the best features of both systems.
PROGRESS IN AUGUST AND SEPTEMBER
During August and September, representatives from Xerox, Symbolics, and
Lucid began work on a draft specification of the standard. This working
group started with the basic programmer interface for defining new classes
and writing methods and generic functions. This work is ongoing, but a
draft of the programmer interface is available - the meta-object protocol
specification will be available soon.
GOALS FOR THE STANDARD
Some high-level goals were stated and agreed-upon:
Sound basis The standard will include the aspects of object-oriented
programming that are well-understood at this time. The
standard will omit ideas that are still subjects for
research.
Flexibility The meta-object protocol of the standard will offer a
flexible framework for other designers to implement
different schemes. This encourages exploration of
different styles of object-oriented programming.
Power The standard will offer the basic tools for writing
programs in an object-oriented style, and will be powerful
enough that it meets the needs of most programs. It should
not be necessary for programmers to extend the system to do
straightforward object-oriented programming.
Simplicity The standard will specify just the language, not the
programming tools and interactive development environment.
Compatibility It should be a convenient and simple procedure to translate
programs written in CommonLoops or New Flavors to the new
standard. We intend to provide tools that will perform the
translation automatically.
Implementation The standard will allow efficient implementation on stock
hardware as well as specialized machines.
FEATURES TO BE INCLUDED IN THE STANDARD
The following features wil be included in the standard.. This is not an
exhaustive list, but is intended to communicate some of the areas of
agreement that have been reached.
Generic functions
The standard will use the normal Lisp function-calling
syntax.
Class and Type Space Merging
Every object in the Lisp system has a class and hence can
be used to select methods.
Dispatching The standard will allow dispatching on the class of one
(classical methods) or more (multi-methods) arguments.
Multiple inheritance
Classes can be combined together freely; they
need not fit into a rigid hierarchy.
Meta-objects The standard defines objects for the major implementation
entities of the system to allow for extensibility.
Classes, methods, and generic functions all have
corresponding objects, organized by well-defined,
documented protocols.
Declarative Method Combination
Method selection and combination can be controlled
declaratively. Users can define new
method combination paradigms.
FUTURE PLANS
The working group is developing a draft specification for the standard.
The specification process will involve the community in the feedback
process.
Portable Common Loops will evolve to to track the new specification. This
portable implementation will enable the community to experiment with and
gain a deeper understanding of the ideas than is possible with only a
specification.
∂17-Sep-86 1636 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: default optional arguments to a generic function
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 16:32:45 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 17 SEP 86 13:18:15 PDT
Return-Path: <Moon@ALDERAAN.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from ALDERAAN.SCRC.Symbolics.COM ([192.10.41.109]) by
Xerox.COM ; 17 SEP 86 13:17:57 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 5208; Wed
17-Sep-86 16:14:22 EDT
Date: Wed, 17 Sep 86 16:15 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: default optional arguments to a generic function
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To:
<860916-103819-6832@Xerox>,<860916135909.5.GREGOR@AVALON.XEROX-PARC>
Message-ID: <860917161551.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 16 Sep 86 10:37 PDT
From: Bobrow.pa@Xerox.COM
GFD #1. the defaults from the defgeneric are used only for method
lookup. This is the kind I described above.
GFD #2. the defaults from the defgeneric are used for method lookup
and also passed to the method.
There is a fundamental conceptual difference. I think the notion of
supplying defaults is part of the contract between the generic function
and the world.
I agree.
This is an argument for GFD #1. We all seem to agree
that defmethods, if they specify optionals, must agree with the generic
function. If the EQUALS rule is used for defaults (I support this),
then I see no reason for the default forms to be evaluated twice.
This is an argument for GFD #2, I assume. In GFD #1 I don't see how to
avoid evaluating the default forms twice.
If
methods can have exactly the same supplied-p args as specified in the
generic function (no more, no less - just local renaming allowed) then
there is no penalty for passing supplied-p args to each method as
"required args". The calling sequence is uniform.
Supplied-p parameters are -not- part of the contract between the generic
function and the world, so requiring them to be the same in all methods
is a bit strange. It's possible that this is the price we have to pay
to make everything work, but it's ugly.
Given:
(defgeneric foo (x &optional y (z *v1* supplied-z)) ...)
then the following is legal
(defmethod foo ((x c1) &optional ((y c2)) (z *v1* my-supplied-z))) ..)
and the following are illegal
(defmethod foo ((x c1) &optional (y NIL supplied-y)(z *v1*
my-supplied-z))) ..)
(defmethod foo ((x c1) &optional y (z *v1* ))) ..)
One issue to be addressed is the following. If we insist on the EQUALS
rule, then if the default value form changes in the defgeneric, it must
be changed in all methods. This redundancy is bad design.
On the other hand, not having the default value lexically visible in the
method could be argued by some people as bad design. It's a difficult
situation.
To allow
arg-specification and supplied-p specification, I suggest another
keyword &optional-spec. Following &optional-spec can be
{varName|(varName arg-specifier [supplied-p-var])}*
where the interpretation is the obvious one, given in my message of last
week. The rule of supplied-p correspondence still holds, but no default
value form need be specified.
I think we need a better name than &optional-spec, but otherwise this
sounds reasonable, assuming that we want a way to do this. The message
from Gregor below raises questions about whether discriminating on
optional arguments is going to fly at all.
Date: Tue, 16 Sep 86 13:59 PDT
From: Gregor.pa@Xerox.COM
Subject: the kinds of method lookup people claim they want
I spent lunch today listening to people talk about the kinds of method
lookup which they would like to have CommonLoops support. I was struck
by the variety of things which people claimed would be natural or
convenient or even essential. By the end of lunch I was very confused
about what we should do about discriminating on optional arguments.
In the interest of confusing the rest of you, I thought I would collect a
list of all the cases of method definition people thought they would
want. Please add any other examples or potential screw cases.
NOTE: In each of these examples I have used some syntax and some
defining forms which I intend only to express the example. Do not
regard the syntax I have used as a proposal for how we should do
anything.
Case 1a. "draw-line"
draw-line takes an optional, the width of the line in device dependent
units. Because they are device dependent units, each individual method
would like to default this argument on its own.
(defmethod draw-line ((dev printer) p1 p2 &optional (width 7))
...)
(defmethod draw-line ((dev window) p1 p2 &optional (width 1))
...)
Case 1b.
Within case 1, some methods may want to take an extra argument. Also
see case 3 which is similar.
(defmethod draw-line ((d gray-display) p1 p2
&optional (width 3)
(gray *gray1*))
..)
The problem here is that the generic function doesn't have a consistent
contract. The meaning, or even the existence, of one argument depends
on the class of another argument. I don't see how a caller of draw-line
could operate without knowing the exact method that was going to be called.
From experience I know it's possible to have all sorts of arguments about
whether this is good or bad programming practice. In New Flavors, these
arguments were resolved in favor of consistency of contracts, rather than
the increased flexibility of different contracts for different methods,
but not everyone was happy.
The rules I proposed earlier for consistency of defgeneric and defmethod
lambda-lists, which Danny seems to agree with, would rule out both 1a and
1b. I don't know what to say about this; it may be impossible to please
all of the people all of the time.
Case 2. "draw (GFD#2)"
The generic function takes an optional argument. For all the methods,
the optional argument should default to the same value. In addition,
method lookup should be based on the value of the optional argument
(after defaulting) and the defaulted value should be passed in. This
corresponds to what I previously called GFD#2.
(defgeneric draw (thing &optional (place *draw-window*))
"Draw thing on place.")
(defmethod draw ((thing line) (place raster-display)) ...)
(defmethod draw ((thing line) (place vector-display)) ...)
People have also said that within the individual methods they would like
to have access to the supplied-p information for the optional argument.
Current ideas seem to be able to satisfy this one.
Case 3. "move"
A generic function (e.g. move) has only classical methods. Some of the
methods want to accept more arguments than others. For example: move
when then first argument is a block takes a position to move to, but
move when the first argument is a rabbit takes no extra arguments (the
rabbit will jump up and down).
(defmethod move ((b block) to-x to-y) ..)
(defmethod move ((r rabbit)) ..)
This is another case where the function isn't really generic, because
it can only be meaningfully called by someone who knows exactly which
method is being called.
Case 4. "Guy's proposal"
In this porposal, method lookup checks argument specifiers for only the
supplied arguments. When there are two arguments supplied, the most
specific of the two argument methods is called.
(defmethod foo (a b &optional (c x) (d y)) body)
is simply an abbreviation for
(defmethod foo (a b) (let ((c x) (d y)) body))
(defmethod foo (a b c) (let ((d y)) body))
(defmethod foo (a b c d) body)
So that:
(defmethod gls ((a boat) &optional ((p plane) *default*)) ..)
(defmethod gls ((a speed-boat)) ...)
(foo <a speed-boat>) ;runs method 2
(foo <a speed-boat> <a plane>) ;runs method 1
I hope this one has already been discredited as so confusing that no
one can cope with it.
-+-+-+-
Seeing all these different, and maybe not even mutually compatible,
things that people would like us to do, it is possible that we are
going to have to take the conservative approach and say that for now
we are only going to support discrimination on required arguments,
because discrimination on optional and keyword arguments is not yet
well-understood and there is not yet a concensus among users on which
to base a standard. GFD #2 can be achieved within this framework
by the expedient of defining an "interface function" that defaults
the arguments, for instance:
(defun draw (thing &optional (place *draw-window* place-supplied-p))
"Draw thing on place."
(draw-internal thing place place-supplied-p))
(defmethod draw-internal ((thing line) (place raster-display) place-supplied-p) ...)
(defmethod draw-internal ((thing line) (place vector-display) place-supplied-p) ...)
Flavors provides the feature that you don't have to make
up the auxiliary name draw-internal, which is confusing because
the externally visible interface is named draw but you put methods
on draw-internal. You do this by (translating out of the present
Flavors syntax, which is too biased against multimethods):
(defgeneric draw (thing &optional (place *draw-window* place-supplied-p))
"Draw thing on place."
(:method-arguments thing place place-supplied-p)
(:function
(funcall (generic draw) thing place place-supplied-p)))
(defmethod draw ((thing line) (place raster-display) place-supplied-p) ...)
(defmethod draw ((thing line) (place vector-display) place-supplied-p) ...)
∂17-Sep-86 1636 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: run-super, whoppers, wrappers
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 16:32:30 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 17 SEP 86 13:18:01 PDT
Return-Path: <Moon@ALDERAAN.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from ALDERAAN.SCRC.Symbolics.COM ([192.10.41.109]) by
Xerox.COM ; 17 SEP 86 13:17:41 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 5189; Wed
17-Sep-86 15:42:59 EDT
Date: Wed, 17 Sep 86 15:44 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: run-super, whoppers, wrappers
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860917-082814-7626@Xerox>
Message-ID: <860917154410.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 17 Sep 86 08:29 PDT
From: Bobrow.pa@Xerox.COM
To simplify things, I removed :AROUND methods from this version, but
it would only take a few lines of code to put them back in if we wished
to do so.
I would like to see the addition for :around. (What do you think
changing ":around" to ":full-shadow"?)
The same as I thought on 11 September
(Message-ID: <860911172500.4.MOON@EUPHRATES.SCRC.Symbolics.COM>):
The name :full-shadow doesn't convey much meaning to my ear.
I'm not at all attached to the name "around". I was just using it in
the absence of anything better, since it was the name someone else (I
forget who) mentioned. Actually "around" seems to fit with "before" and
"after" better than "full-shadow". I'd say that "around" is a somewhat
clearer name than "full-shadow", which is miles better than "whopper".
If we can find a clearer name than any of these, I'm all for it.
I should mention again that these "around" methods are different from
whoppers, in that they are implemented by a particular type of method
combination, rather than being available automatically to all types of
method combination. If the standard said that all types of method
combination should support "around" methods, then either life would be
more difficult for a user wanting to define his own type of method
combination or we would have to subroutinize things so that it was
trivially easy for that user to include "around" support. I assume
that subroutinization is possible, but I haven't thought out the details.
I may not have made it clear that I don't care whether whoppers per se
are in the standard as long as there is something with equivalent
functionality in the standard. "Around" methods would suffice, I think.
Wrappers appear to be more powerful than "around" methods, at least in
terms of efficiency (eliminating function calls), but perhaps that can
be licked with an INLINE proclamation; I ought to think about this more.
For purposes of agreement before OOPSLA you don't need to think about
wrappers at all; I'll bring them up later if I don't convince myself
they aren't needed.
The particular feature I am interested
in is how you express the transformation of a form to a method.
The same way you always convert a form to a function, with lambda. The
code is at the end of this message.
Is
this what your were referring to in:
;;;; This scheme uses more machine-dependencies to avoid
;;;; an extra level of lambda in the continuations.
Not exactly. The two earlier implementations of run-super required an
extra lambda for every method called by run-super, for no good reason.
The body of the lambda was just a call-component-method of the method, I
think. This version eliminates those and calls the methods directly.
The cost of this efficiency improvement is that the RUN-SUPER macrolet
put into methods by TRANSFORM-SUPER-DAEMON-METHOD has to contain
additional hair to pass the arguments along, instead of just funcalling
the continuation with no arguments, and hence more of the Flavors
implementation is visible instead of abstracted out of sight; more about
this below.
The important thing is the semantics of how RUN-SUPER and
method-combination fit together, which is:
all the :BEFORE methods are executed, most-specific first the
most specific primary method is executed, and supplies the value(s)
if it uses RUN-SUPER, that calls the next primary method,
and so on if RUN-SUPER exhausts the supply of primary methods, it
signals an error
all the :AFTER methods are executed, least-specific first
Shall we make this the default method-combination type, or does
anyone object? (Myself, I object to the name RUN-SUPER, and maybe we
can think of a more expressive name. If not, I can live with that one.)
I am happy with this as the default. I have no better name than run-super.
run-continuation is not semantically correct, and super has a history people
can relate to.
Agreed.
I don't like the name "super-daemon" or even "daemon",
although history rgues for each of those. How about "simple-nested". or just
"nested" sincer the primary is nested in befores and afters, and run-super
does dynamically controlled nesting.
"super-daemon" was just a name I was using in the absence of a suggested
name and wasn't a proposal for the standard. I needed a name so I could
debug my code without clobbering the existing Flavors code. In the
standard there would be no need to have two distinct method-combination
types, one that does daemons but not run-super, and another that does
daemons and run-super, so fewer names would be required. "Nested"
doesn't convey any meaning to my ear. The way to really wimp out would
be to call this type of method-combination "default", since it will be
the default type. I'd rather have a more descriptive name, though. Any
ideas? My default assumption for right now is that it will be named
"daemon", but I'm not attached to that name. We don't actually need a
name for this in order to reach agreement on the list of things I
proposed last night as a reasonable agenda for the document to be handed
out at OOPSLA.
I would want to describe super-daemon in the spec in pieces.
The first would describe the specifcation of run-super alone as in Loops. Then
I would describe standar declarative method combination, and the interaction.
Finally, I would want to describe the method combination language that allows
these to be defined.
This sounds good. This is an extension of the way we do it now:
First we describe solitary methods so there is no combination issue.
Then we describe having one primary method shadow another. Here you
add run-super. Then we describe :before, :after, and now :around methods.
Then we describe other built-in types of method-combination. Then we
describe how to make your own types of method-combination.
Here is the revised code for the method-combination type. The only
other change is to make TRANSFORM-SUPER-DAEMON-METHOD treat around
methods the same as primary methods. Note that if I was going to
install this code I would first want to define some more abstractions,
similar to CALL-COMPONENT-METHOD, to hide the messy and
machine-dependent details of the method calling sequences. I didn't do
that in this version because I wanted to make it work first and then
think about what the appropriate abstractions would be. Another thing I
would want to do is to redo the STACK-LET since those lists are actually
constant, changing only when a change to the class structure occurs or a
method is redefined. For this version I construct the continuation list
every time, and then use STACK-LET instead of LET to eliminate the
consing, but it would be better to construct the list once and arrange
for it to be updated when the class structure changes. This is the sort
of place where I start wishing for meta-object protocols. I don't want
to spend time thinking about this until after OOPSLA, but for now I'm
assuming that the Common Lisp Classes version of this
DEFINE-METHOD-COMBINATION would be much less ugly, because it would be
built on top of those abstractions and protocols.
(DEFINE-METHOD-COMBINATION :SUPER-DAEMON ()
((AROUND "around" :EVERY :MOST-SPECIFIC-FIRST (:AROUND))
(BEFORE "before" :EVERY :MOST-SPECIFIC-FIRST (:BEFORE))
(PRIMARY "primary" :EVERY :MOST-SPECIFIC-FIRST () :DEFAULT)
(AFTER "after" :EVERY :MOST-SPECIFIC-LAST (:AFTER)))
(:ARGLIST IGNORE &REST ARGS)
(:METHOD-TRANSFORMER
;; Deal with run-super by transforming the method's arglist and body
(:METHOD-ARGLIST
(MULTIPLE-VALUE-SETQ (METHOD-ARGLIST METHOD-BODY)
(TRANSFORM-SUPER-DAEMON-METHOD FUNCTION-SPEC METHOD-ARGLIST METHOD-BODY)))
(:METHOD-BODY METHOD-BODY))
;; If there are no daemons, the code produced can be optimized
(UNLESS (OR BEFORE AFTER)
(SETQ PRIMARY (NCONC AROUND PRIMARY)
AROUND NIL))
;; Remove from dependencies the primary methods that cannot be reached by RUN-SUPER
(SETQ PRIMARY (LOOP FOR METHOD IN PRIMARY
COLLECT METHOD
WHILE (METHOD-USES-RUN-SUPER METHOD)))
;; Return appropriate method combining form
(IF (NULL AROUND)
`(MULTIPLE-VALUE-PROG2
,(CALL-COMPONENT-METHODS BEFORE)
,(COND ((NULL PRIMARY) `NIL)
((AND (NULL (REST PRIMARY))
(NOT (METHOD-USES-RUN-SUPER (FIRST PRIMARY))))
(CALL-COMPONENT-METHOD (FIRST PRIMARY))) ;Optimize single-method case
(T
;; Stash the machine-dependent information needed for run-super,
;; then call the first primary method, which will call the rest of them.
`(STACK-LET ((*SUPERCLASS-CONTINUATIONS*
(LIST ,@(LOOP FOR METHOD IN (REST PRIMARY)
COLLECT `(FUNCTION ,METHOD)
COLLECT `(GET-FLAVOR-MAPPING-TABLE-FOR-INSTANCE
SELF ',(METHOD-FLAVOR METHOD)))
#'RUN-SUPER-EXHAUSTED)))
,(CALL-COMPONENT-METHOD (FIRST PRIMARY)))))
,(CALL-COMPONENT-METHODS AFTER))
;; With both AROUND methods and daemons, need an internal method to call the daemons
;; and *SUPERCLASS-CONTINUATIONS* has to be bound around the whole thing
`(STACK-LET ((*SUPERCLASS-CONTINUATIONS*
(LIST ,@(LOOP FOR METHOD IN (REST AROUND)
COLLECT `(FUNCTION ,METHOD)
COLLECT `(GET-FLAVOR-MAPPING-TABLE-FOR-INSTANCE
SELF ',(METHOD-FLAVOR METHOD)))
;;--- The arglist of this lambda should be hidden by an
;;--- abstraction, which would also allow it to not need
;;--- to use &REST all the time
#'(LAMBDA (SELF SELF-MAPPING-TABLE .GENERIC. &REST ,ARGS)
(MULTIPLE-VALUE-PROG2
,(CALL-COMPONENT-METHODS BEFORE)
,(CALL-COMPONENT-METHOD (FIRST PRIMARY))
,(CALL-COMPONENT-METHODS AFTER)))
SELF-MAPPING-TABLE
,@(LOOP FOR METHOD IN (REST PRIMARY)
COLLECT `(FUNCTION ,METHOD)
COLLECT `(GET-FLAVOR-MAPPING-TABLE-FOR-INSTANCE
SELF ',(METHOD-FLAVOR METHOD))))))
,(CALL-COMPONENT-METHOD (FIRST AROUND)))))
∂17-Sep-86 1636 Gregor.pa@Xerox.COM required-xxx options to defclass
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 16:32:57 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 17 SEP 86 13:26:58 PDT
Date: 17 Sep 86 13:26 PDT
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: required-xxx options to defclass
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860917-132658-7944@Xerox>
This seems to be an issue that remains to be worked out about defclass.
Until yesterday, I was the only west coast supporter of the
:required-methods etc. options to defclass. But I have finally given in
and conceded that maybe these should not be in the standard.
I had been able to convince people that these options were not, in fact,
merely a programming environment feature. But I finally succumbed to
the argument that:
These options are just hack implementations of something which
*protocols* would do right. Given that we don't have protocols, and we
don't want to clutter the spec with hacks, we should not include these
options. Then, when we do figure out how to do protocols "right", there
won't be these old, obsolete required-xxx options hanging around.
How do you feel about not having :required-xxx options in the standard?
∂17-Sep-86 2028 Owners-CommonLoopsCore↑.pa@Xerox.COM DEFCLASS should replace DEFSTRUCT
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 20:28:46 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 17 SEP 86 16:51:18 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 17 SEP 86 16:50:58 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 106567; Wed
17-Sep-86 19:49:30 EDT
Date: Wed, 17 Sep 86 19:49 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: DEFCLASS should replace DEFSTRUCT
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860917-101441-7733@Xerox>
Message-ID: <860917194955.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 17 Sep 86 10:14 PDT
From: Ken Kahn <Kahn.pa@Xerox.COM>
A few months ago we believed that CommonLoops could just extend
DEFSTRUCT to deal with multiple inheritance and metaclasses. Then there
was this idea that DEFSTRUCT did some things poorly and we could do them
better in DEFCLASS. I am willing to agree to this if the spec proposes
that we flush DEFSTRUCT from Common Lisp and provide a DEFSTRUCT macro
for backwards compatibility that is mostly implemented in CommonLoops.
Why should anyone use DEFSTRUCT anymore?
I believe this should be proposed as a separate standardization item.
I don't think the object-oriented programming standard should stand or
fall on the basis of irrelevant considerations such as whether someone
out there is particularly attached to DEFSTRUCT.
∂17-Sep-86 2029 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: run-super
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 20:28:52 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 17 SEP 86 17:02:09 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 17 SEP 86 17:01:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 106573; Wed
17-Sep-86 20:00:05 EDT
Date: Wed, 17 Sep 86 20:00 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: run-super
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860917-093011-7680@Xerox>
Message-ID: <860917200030.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 17 Sep 86 09:29 PDT
From: Kahn.pa@Xerox.COM, Bobrow.pa@Xerox.COM
Regarding your code
(DEFINE-METHOD-COMBINATION :SUPER-DAEMON ()
...
;; Remove from dependencies the primary methods that cannot be reached
by RUN-SUPER
(SETQ PRIMARY (LOOP FOR METHOD IN PRIMARY
COLLECT METHOD
WHILE (METHOD-USES-RUN-SUPER METHOD)))
;; Return appropriate method combining form
...)
The last method in the primary list should be the first one that does
not use run-super.
That's exactly what that code does. You may have been misled by thinking
that LOOP executes its clauses out of order, the way Interlisp FOR does.
The above LOOP stops -after- collecting the method for which
METHOD-USES-RUN-SUPER is false.
Only if all primary methods use run-super,
#'RUN-SUPER-EXHAUSTED must be inserted at the end of the list.
That's true, the list could be shortened by one element in the case
where the last element is unreachable. I'll put a comment in my copy of
that program saying that it should be optimized. Also, I forgot to
include #'RUN-SUPER-EXHAUSTED at the end of the list in the
around-method case, in the revised version of the code I mailed out
earlier today.
It is
not an error for all primary methods to call run-super since in some
contexts the last primary method may be in another position in the
*SUPERCLASS-CONTINUATIONS* list.
That's a good point. That sinks my idea of detecting the
RUN-SUPER-EXHAUSTED at compile time instead of at run time; good, I can
stop worrying about that.
We might also then define run-super?
that returns NIL if the next continuation is #'RUN-SUPER-EXHAUSTED.
Yes, we could do that. Note that standard Common Lisp functions aren't
allowed to have question marks in their names, but I'm sure we could think
of a better name.
∂17-Sep-86 2029 Masinter.pa@Xerox.COM Re: DEFCLASS should replace DEFSTRUCT
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 20:28:58 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 17 SEP 86 19:52:38 PDT
Date: 17 Sep 86 19:50 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: DEFCLASS should replace DEFSTRUCT
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 17 Sep 86 19:49 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860917-195238-8313@Xerox>
I disagree (rather violently). I think that the reason that CommonLoops
was originally acceptable to a large class of people was that it did not
add substantially to the complexity of the Language. The acceptability
of CommonLoops partially on that principle, and any movement away from
it risks losing it.
It is certainly not a separable consideration.
Similarly, a syntax where DEFUN was syntactically compatible with
DEFMETHOD (or whatever its method alias is called) is another important
simplification of Common Lisp. Making a large number of alternative
forms, adding DEFGENERIC, and number of the other proposed extentions
which have been added by this negotiating group are a potentially
drastic movement away from the simplicity in the original proposal.
I had been misled into believing the discussions on CommonLoopsCore↑ was
an attempt to do some minor tuning on the way that metaclasses were set
up and initialization. Into the conversation for a couple of days, I've
found that things have drifted radically away from what we and many
others have agreed to support.
/sub
"commonloopscore↑.pa"@xerox
DEFCLASS should replace DEFSTRUCT
I bow to those who use mailers that sort mail according to subject:
My message is responsive to the discussion which has gone on under
this subject line, but the contents of my remarks and of the remarks
to which I reply bear no semantic relationship to the subject line.
There indeed was a simplicity in the early CommonLoops proposal, but the
simplicity was the simplicity of a naive proposal. In particular, the
use of Defmethod as a vague replacement for Defun to create a cloud of
functions that are invoked variously misses the goal of a clearly understood
construct. What precisely is the contract between this cloud and the outside
world? How does this cloud relate to Lisp functions? If you can FUNCALL this
cloud, can you affect it by affecting the thing that sits in the symbol-function
cell of a symbol? Simply stated, is the cloud a first-class object, or is it
like the heap?
The `negotiating' group is doing more than negotiating: It is attempting to
bring some design sense into the picture. The early CommonLoops proposal
was more like a slogan than a well-designed system.
-rpg-
∂17-Sep-86 2031 Owners-CommonLoopsCore↑.pa@Xerox.COM Proposed Goals (Statement for OOPSLA)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 20:29:10 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 17 SEP 86 19:54:42 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 17 SEP 86 19:53:16 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 106633; Wed
17-Sep-86 22:51:47 EDT
Date: Wed, 17 Sep 86 22:52 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Proposed Goals (Statement for OOPSLA)
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860917-113216-7821@Xerox>
Message-ID: <860917225211.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 17 Sep 86 11:33 PDT
From: Bobrow.pa@Xerox.COM
Dick edited Sonya's version, then Danny and Gregor edited his to produce
this.
All of the changes are okay with me, except that I have problems with the
style of this one:
In brief, the standard will be based on the meta-object framework of
CommonLoops, which allows experimentation with different philosophies of
object-oriented programming. Additional features from new Flavors will
be added to CommonLoops to flesh out the programmer interface; in
particular, a declarative method combination facility patterned after
that in new Flavors has been added to CommonLoops to create an extension
to Common Lisp that represents the best features of both systems.
This confuses what has been done to CommonLoops so far, adding some
Flavors ideas, with the definition of the standard. Those are two
different things. I think I understand what you're trying to get at
with this improvement of the earlier version of this paragraph, and I'd
like to propose this revision:
In brief, the standard will be based on the meta-object framework of
CommonLoops, which allows experimentation with different philosophies of
object-oriented programming. The programmer interface on top of this
framework will combine the most useful features of CommonLoops and New
Flavors, such as multimethods from CommonLoops and declarative method
combination from Flavors. The standard will be an extension to Common
Lisp that incorporates the best features of both systems.
∂17-Sep-86 2224 Owners-CommonLoopsCore↑.pa@Xerox.COM The name of WITH
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 22:24:06 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 17 SEP 86 20:37:55 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 17 SEP 86 20:37:44 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 106656; Wed
17-Sep-86 23:34:14 EDT
Date: Wed, 17 Sep 86 23:34 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: The name of WITH
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860917-131252-7924@Xerox>
Message-ID: <860917233439.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 17 Sep 86 13:12 PDT
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
If people really think the name WITH is too short, then the name
WITH-SLOTS seems like the obvious best name to me.
That sounds good to me too.
∂17-Sep-86 2224 Owners-CommonLoopsCore↑.pa@Xerox.COM required-xxx options to defclass
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Sep 86 22:24:14 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 17 SEP 86 20:55:02 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 17 SEP 86 20:54:52 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 106667; Wed
17-Sep-86 23:52:13 EDT
Date: Wed, 17 Sep 86 23:52 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: required-xxx options to defclass
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860917-132658-7944@Xerox>
Message-ID: <860917235226.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 17 Sep 86 13:26 PDT
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
These options are just hack implementations of something which
*protocols* would do right. Given that we don't have protocols, and we
don't want to clutter the spec with hacks, we should not include these
options. Then, when we do figure out how to do protocols "right", there
won't be these old, obsolete required-xxx options hanging around.
How do you feel about not having :required-xxx options in the standard?
I'm not convinced that protocols will eliminate the :required-xxx
options. However, I agree that the "sound basis" item in our professed
statement of goals requires that things we suspect, after sufficient
discussion, are not well understood should not be included.
The question, then, is whether these are sufficiently indispensable to
users to justify including them anyway (the "power" and "compatibility"
goals). In this case I think the answer is no. So let's leave these
out of the standard for now.
∂18-Sep-86 0625 Owners-CommonLoopsCore↑.pa@Xerox.COM The name of WITH
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 06:25:36 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 18 SEP 86 05:29:12 PDT
Return-Path: <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 18 SEP 86 05:29:01 PDT
Received: from JUNCO.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 106773; Thu
18-Sep-86 08:19:01 EDT
Date: Thu, 18 Sep 86 08:17 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: The name of WITH
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860917233439.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <860918081727.4.SKEENE@JUNCO.SCRC.Symbolics.COM>
Line-fold: No
Date: Wed, 17 Sep 86 23:34 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Date: 17 Sep 86 13:12 PDT
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
If people really think the name WITH is too short, then the name
WITH-SLOTS seems like the obvious best name to me.
That sounds good to me too.
Does WITH-SLOTS only give you variables for each slot, or does it also
give you a "SELF" variable for the object itself? If it also provides
a variable for the object, maybe WITH-INSTANCE would be a better name.
∂18-Sep-86 0811 Owners-CommonLoopsCore↑.pa@Xerox.COM Proposed Goals (Statement for OOPSLA)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 08:11:33 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 18 SEP 86 07:43:05 PDT
Return-Path: <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 18 SEP 86 07:42:09 PDT
Received: from JUNCO.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 106864; Thu
18-Sep-86 10:34:54 EDT
Date: Thu, 18 Sep 86 10:33 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Proposed Goals (Statement for OOPSLA)
To: Bobrow.pa@Xerox.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860917-113216-7821@Xerox>
Message-ID: <860918103320.8.SKEENE@JUNCO.SCRC.Symbolics.COM>
Line-fold: No
Date: 17 Sep 86 11:33 PDT
From: Bobrow.pa@Xerox.COM
Dick edited Sonya's version, then Danny and Gregor edited his to produce
this.
Thanks for your quick response on this. I've revised the text of this
statement to include your changes (except for one paragraph), and I also
corrected a few typos in your version. Anything that I changed from
your version is enclosed in *asterisks* below.
Moon has sent another version of the paragraph in question for you to
comment on. It's also included here.
HISTORY AND MOTIVATION
There is currently substantial experience with object-oriented
programming paradigms within a variety of contexts. The two groups
*have have* the most experience in this area are Symbolics and Xerox.
Only one "have"
Flavors, an important object-oriented programming extension to Lisp,
has been in use for more than 7 years. Over that period many valuable
lessons
have been learned about object-oriented programming in Lisp. In 1985,
Symbolics took these lessons to heart and designed New Flavors, which
is a compatible extension to Flavors.
Xerox has had more than 10 years of experience with object-oriented
programming, both within the Lisp tradition and within the Smalltalk
tradition. Over that period many lessons were learned, and in 1985
Xerox
began to design a new object-oriented programming extension to Common
Lisp, called CommonLoops.
In mid-1985 these two groups became aware of each other. These
two object-oriented extensions to Lisp had important similarities.
CommonLoops evolved to include some of the ideas in *new Flavors*.
Capitalize "New Flavors".
Many people in the Common Lisp community now see a need for defining a
standard for object-oriented programming that would be part of Common
Lisp. The primary benefit of such a standard would be the ability to
write portable Common Lisp code in an object-oriented style.
At the Common Lisp committee meeting in Boston in December 1985, many
vendors of application software made it clear how important such a
standard is to them. Again at the ACM Conference on Lisp and Functional
Programming in Cambridge in August 1986, the same point was made.
After the ACM Conference there was a meeting of the Common Lisp
Object-oriented Programming Committee. A clear consensus was reached
that
work should begin immediately to define a standard. Representatives
from Xerox, Lucid, Symbolics, LMI, HP, Sun, and the Japanese CommonLisp
committee supported this consensus.
A working group composed of representatives from Xerox and Symbolics met
after the ACM Conference; at the meeting this working group reached
agreement on several general goals.
*In brief, the standard will be based on the meta-object framework of
CommonLoops, which allows experimentation with different philosophies of
object-oriented programming. Additional features from new Flavors will
be added to CommonLoops to flesh out the programmer interface; in
particular, a declarative method combination facility patterned after
that in new Flavors has been added to CommonLoops to create an extension
to Common Lisp that represents the best features of both systems.*
We prefer the paragraph below, because it makes it clear that the new
thing isn't CommonLoops:
"In brief, the standard will be based on the meta-object framework of
CommonLoops, which allows experimentation with different philosophies of
object-oriented programming. The programmer interface on top of this
framework will combine the most useful features of CommonLoops and New
Flavors, such as multimethods from CommonLoops and declarative method
combination from Flavors. The standard will be an extension to Common
Lisp that incorporates the best features of both systems."
PROGRESS IN AUGUST AND SEPTEMBER
During August and September, representatives from Xerox, Symbolics, and
Lucid began work on a draft specification of the standard. This working
group started with the basic programmer interface for defining new
classes
and writing methods and generic functions. *This work is ongoing, but a
draft of the programmer interface is available - the meta-object
protocol specification will be available soon.*
Let's make that two complete sentences: "This work is ongoing, but a
draft of the programmer interface is available. The meta-object
protocol specification will be available soon."
GOALS FOR THE STANDARD
Some high-level goals were stated and agreed-upon:
Sound basis The standard will include the aspects of object-oriented
programming that are well-understood at this time. The
standard will omit ideas that are still subjects for
research.
Flexibility The meta-object protocol of the standard will offer a
flexible framework for other designers to implement
different schemes. This encourages exploration of
different styles of object-oriented programming.
Power The standard will offer the basic tools for writing
programs in an object-oriented style, and will be
powerful
enough that it meets the needs of most programs. It
should
not be necessary for programmers to extend the system to
do
straightforward object-oriented programming.
Simplicity The standard will specify just the language, not the
programming tools and interactive development
environment.
Compatibility It should be a convenient and simple procedure to
translate
programs written in CommonLoops or New Flavors to the
new
standard. We intend to provide tools that will perform
the
translation automatically.
Implementation The standard will allow efficient implementation on
stock
hardware as well as specialized machines.
FEATURES TO BE INCLUDED IN THE STANDARD
The following features *wil be* included in the standard.. This is not an
"will be"
exhaustive list, but is intended to communicate some of the areas of
agreement that have been reached.
Generic functions
The standard will use the normal Lisp function-calling
syntax.
Class and Type Space Merging
Every object in the Lisp system has a class and hence
can
be used to select methods.
Dispatching The standard will allow dispatching on the class of one
(classical methods) or more (multi-methods) arguments.
Multiple inheritance
Classes can be combined together freely; they
need not fit into a rigid hierarchy.
Meta-objects The standard defines objects for the major
implementation
entities of the system to allow for extensibility.
Classes, methods, and generic functions all have
corresponding objects, organized by well-defined,
documented protocols.
Declarative Method Combination
Method selection and combination can be controlled
declaratively. Users can define new
method combination paradigms.
FUTURE PLANS
The working group is developing a draft specification for the
standard. The specification process will involve the community in the
feedback process.
*Portable Common Loops will evolve to to track the new specification.
This portable implementation will enable the community to experiment
with and
gain a deeper understanding of the ideas than is possible with only a
specification.*
A. Only one "to".
B. I prefer my original text "We wil produce a portable implementation
by evolving Portable Common Loops..." instead of your "Portable Common
Loops will evolve..." PCL isn't going to evolve spontaneously.
How about saying "Xerox will update Portable Common Loops to track the
new specification?"
C. Let's recast that last sentence to take the distracting clause out of the
middle.
That paragraph turns into:
"Xerox will update Portable Common Loops to track the new specification.
By experimenting with the portable implementation, the community can
gain a deeper understanding of the ideas than would be possible by
reading the specification alone."
/sub
"commonloopscore↑.pa"@xerox
Proposed Goals (Statement for OOPSLA)
Sonya's improvements are generally good. I changed her original
sentence
``We will produce a portable implementation by evolving Portable
Common Loops...''
because it can parse in a funny way if you use a slightly less primary
definition of `evolve' than `to exhibit or produce through evolution.'
The definition is `to emit' as in `to evolve gases.' I parsed it as
it would appear in this sentence:
``Danny Bobrow ate a large plate of refried beans last night, went
back to PARC, and accidentally evolved Portable Common Loops. He
apologized profusely for his bad manners.''
Your rephrasing is better than mine, but it does commit Xerox to doing
the work of updating PCL, which they may elect not to do.
One reason for the phrasing of the pedigree paragraph is to emphasize
that the influence of New Flavors on CommonLoops has been going on for
over a year, and that the proposed standard will be more nearly along
the line of evolution, if you will, of CommonLoops as influenced by
New Flavors than a fresh merging of the two systems off the lines of
either. That is, the proposed standard will not be especially like
the CommonLoops of a year ago, but it will be very much like the
CommonLoops of today, because a movement towards New Flavors has
already taken place.
The reason for wanting to reason this way is to give the community
some sense of continuity over the past year. People will possibly rest
more comfortably if they believe that the ideas have developed over a
year's time rather than over a month's time.
The proposed standard will be what it will be, and its pedigree will
be of interest only to historians, and those historians will be able
to see the family lines accurately.
-rpg-
∂18-Sep-86 0900 Bobrow.pa@Xerox.COM Re: The name of WITH
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 08:59:51 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 18 SEP 86 08:26:50 PDT
Date: 18 Sep 86 08:28 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: The name of WITH
In-reply-to: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 18 Sep 86 08:17 EDT
To: skeene@STONY-BROOK.SCRC.Symbolics.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860918-082650-8617@Xerox>
Does WITH-SLOTS only give you variables for each slot, or does it
also give you a "SELF" variable for the object itself? If it
also
provides a variable for the object, maybe WITH-INSTANCE would be a
better name.
In the standard syntax for methods, there is no special name self. The
user chooses the name for an object. WITH-SLOTS allows you access slots
using a variable name. For example,
(defclass point () ((x 0) (y 0)) (accessors-with-prefix point-))
(defmethod move ((p point) dx dy)
(with-slots (p) ;; p is known to be a point from the method-signature
(setq x (+ x dx) y (+ y dy))))
In this example, p could have been used to refer to the point itself.
(+ x dx) expands to
(+ (point-x p) dx) etc.
Using %with-slots
(%with-slots (p) (setq x (+ x dx) y (+ y dy))))
(+ x dx) expands to
(+ (get-slot p x) dx)
The syntax of with-slots is:
(with-slots ({var-name|(var-name var-prefix [class-name]}*) . body)
In the simple case, where only a var-name is used, it is assumed that
the class of the named variable can be determined from the method
signature. Slot-names from the class can be used to access slots of the
object bound to var-name. This is illustrated above.
If two or more var-names are given, then they must have disjoint sets of
names for slots to avoid ambiguity of reference. (but see var-prefix
below). In such a case an error is signalled.
If var-prefix is provided, then references to any slot <slot1> can be
made using the symbol (concat var-prefix <slot1>). This allows easy
reference to two objects of the same class. For example,
(defmethod make-same-height ((p1 point) (p2 point))
;;; set the y coord of p1 to the y of p2, its reference.
;;; slots of p1 are accessed using the slot names
;;; slots of p2 are accessed using ref-<slot-name>
(with-slots (p1 (p2 ref-)) (setq y ref-y)))
Under some circumstances, the class of an object will not be computable
from the method signature, but can be specified by the user.
For example,
(defmethod make-horizontal ((l line))
(let((left (left-point l)) (right (right-point l)))
(with-slots ((left left- point)(right right- point))
(setq left-y right-y))))
These last examples are silly in that one would not go to this trouble
to reference a single variable. But with-slots is very convenient if
you want to do many references.
The scope of these names is lexical (as is obvious from their
trranslation).
%with-slots is identical to with, except that
with-slots expands slot references to access functions and
%with-slots expands slot references to direct accesses
-- danny
∂18-Sep-86 0900 Bobrow.pa@Xerox.COM Re: DEFCLASS should replace DEFSTRUCT
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 08:59:59 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 18 SEP 86 08:36:41 PDT
Date: 18 Sep 86 08:38 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: DEFCLASS should replace DEFSTRUCT
In-reply-to: Masinter.pa's message of 17 Sep 86 19:50 PDT
To: Masinter.pa@Xerox.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860918-083641-8627@Xerox>
I think that the reason that CommonLoops was originally acceptable
to a large class of people was that it did not add substantially to
the complexity of the Language. The acceptability of CommonLoops
partially on that principle, and any movement away from it
risks losing it.
I think simplifying Common Lisp is an admirable goal, and when this
standard is agreed on, I think the Common Lips community can take on
itself the task of redefining old features on top of the new. Not only
do I think that defstruct should go away, but the sequence functions
should be made methods, errors should use objects, the type system
should be described in terms of predications, classes, etc. This
layering of Common Lisp would make a lot cleaner language. Let us put
these items on our agenda.
BUT we have not yet got an object standard!!!! We should keep those
goals in the back of our mind, and try to enable such folding. The job
in front of us at the moment is to ensure we have a useful object
standard.
-- danny
∂18-Sep-86 1100 Owners-commonloopscore↑.pa@Xerox.COM DEFCLASS should replace DEFSTRUCT
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 10:59:08 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 18 SEP 86 10:16:46 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 18 SEP 86
10:16:32 PDT
Date: 18 Sep 86 10:16 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: DEFCLASS should replace DEFSTRUCT
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860918-101646-8740@Xerox>
I bow to those who use mailers that sort mail according to subject:
My message is responsive to the discussion which has gone on under
this subject line, but the contents of my remarks and of the remarks
to which I reply bear no semantic relationship to the subject line.
There indeed was a simplicity in the early CommonLoops proposal, but the
simplicity was the simplicity of a naive proposal. In particular, the
use of Defmethod as a vague replacement for Defun to create a cloud of
functions that are invoked variously misses the goal of a clearly understood
construct. What precisely is the contract between this cloud and the outside
world? How does this cloud relate to Lisp functions? If you can FUNCALL this
cloud, can you affect it by affecting the thing that sits in the symbol-function
cell of a symbol? Simply stated, is the cloud a first-class object, or is it
like the heap?
The `negotiating' group is doing more than negotiating: It is attempting to
bring some design sense into the picture. The early CommonLoops proposal
was more like a slogan than a well-designed system.
-rpg-
∂18-Sep-86 1100 Owners-commonloopscore↑.pa@Xerox.COM Proposed Goals (Statement for OOPSLA)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 10:59:02 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 18 SEP 86 10:02:49 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 18 SEP 86
10:02:32 PDT
Date: 18 Sep 86 10:01 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: Proposed Goals (Statement for OOPSLA)
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860918-100249-8718@Xerox>
Sonya's improvements are generally good. I changed her original
sentence
``We will produce a portable implementation by evolving Portable
Common Loops...''
because it can parse in a funny way if you use a slightly less primary
definition of `evolve' than `to exhibit or produce through evolution.'
The definition is `to emit' as in `to evolve gases.' I parsed it as
it would appear in this sentence:
``Danny Bobrow ate a large plate of refried beans last night, went
back to PARC, and accidentally evolved Portable Common Loops. He
apologized profusely for his bad manners.''
Your rephrasing is better than mine, but it does commit Xerox to doing
the work of updating PCL, which they may elect not to do.
One reason for the phrasing of the pedigree paragraph is to emphasize
that the influence of New Flavors on CommonLoops has been going on for
over a year, and that the proposed standard will be more nearly along
the line of evolution, if you will, of CommonLoops as influenced by
New Flavors than a fresh merging of the two systems off the lines of
either. That is, the proposed standard will not be especially like
the CommonLoops of a year ago, but it will be very much like the
CommonLoops of today, because a movement towards New Flavors has
already taken place.
The reason for wanting to reason this way is to give the community
some sense of continuity over the past year. People will possibly rest
more comfortably if they believe that the ideas have developed over a
year's time rather than over a month's time.
The proposed standard will be what it will be, and its pedigree will
be of interest only to historians, and those historians will be able
to see the family lines accurately.
-rpg-
∂18-Sep-86 1100 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: The name of WITH
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 10:59:16 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 18 SEP 86 10:57:33 PDT
Return-Path: <skeene@ALDERAAN.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from ALDERAAN.SCRC.Symbolics.COM ([192.10.41.109]) by
Xerox.COM ; 18 SEP 86 10:57:06 PDT
Received: from JUNCO.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM
via CHAOS with CHAOS-MAIL id 5379; Thu 18-Sep-86 13:52:29 EDT
Date: Thu, 18 Sep 86 13:51 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: The name of WITH
To: Bobrow.pa@Xerox.COM
cc: skeene@STONY-BROOK.SCRC.Symbolics.COM,
Moon@STONY-BROOK.SCRC.Symbolics.COM, CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860918-082650-8617@Xerox>
Message-ID: <860918135152.0.SKEENE@JUNCO.SCRC.Symbolics.COM>
Line-fold: No
Date: 18 Sep 86 08:28 PDT
From: Bobrow.pa@Xerox.COM
Thanks for the information on WITH-SLOTS. I have two questions.
Does WITH-SLOTS only give you variables for each slot, or does it
also give you a "SELF" variable for the object itself? If it
also
provides a variable for the object, maybe WITH-INSTANCE would be a
better name.
In the standard syntax for methods, there is no special name self. The
user chooses the name for an object. WITH-SLOTS allows you access slots
using a variable name. For example,
(defclass point () ((x 0) (y 0)) (accessors-with-prefix point-))
If the class of point had been defined without specifying the
:accessors-with-prefix option, what happens when you define (or run?)
the method below?
(defmethod move ((p point) dx dy)
(with-slots (p) ;; p is known to be a point from the method-signature
(setq x (+ x dx) y (+ y dy))))
In this example, p could have been used to refer to the point itself.
(+ x dx) expands to
(+ (point-x p) dx) etc.
Using %with-slots
(%with-slots (p) (setq x (+ x dx) y (+ y dy))))
(+ x dx) expands to
(+ (get-slot p x) dx)
[text deleted here on syntax of WITH-SLOTS]
%with-slots is identical to with, except that
with-slots expands slot references to access functions and
%with-slots expands slot references to direct accesses
So, I guess the idea is this: You would use %WITH-SLOTS if you really
wanted full access to the slots whether or not they were declared to be
accessible in the DEFCLASS. You would use WITH-SLOTS if you wanted
the system to prevent you from accessing a slot that was not declared
accessible in the DEFCLASS. Another reason to use WITH-SLOTS is to
ensure that the accessor generic function is run -- which might include
some :before or :after methods.
∂18-Sep-86 1306 Owners-CommonLoopsCore↑.pa@Xerox.COM WITH-SLOTS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 13:06:10 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 18 SEP 86 11:02:27 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 18 SEP 86 11:02:01 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 107073; Thu
18-Sep-86 13:58:43 EDT
Date: Thu, 18 Sep 86 13:58 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: WITH-SLOTS
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860918-082650-8617@Xerox>
Message-ID: <860918135841.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 18 Sep 86 08:28 PDT
From: Bobrow.pa@Xerox.COM
WITH-SLOTS allows you access slots using a variable name. For example...
The syntax of with-slots is:
(with-slots ({var-name|(var-name var-prefix [class-name]}*) . body)
It's nice to see a concrete specification of something. I have some
syntactic suggestions: I think it would be clearer to use keyword arguments
rather than a mixture of positional arguments and multiple operator names.
I would suggest these three keywords:
:class class-name -- the class, or a super class, of the instance.
:prefix string -- prefixed to the slot names (can be a symbol or a string).
:direct boolean -- t means access slots directly, nil means call the
accessor functions, which might invoke methods.
Thus the syntax would become
(with-slots ({var-name|(var-name &key class prefix direct) . body)
and your examples would become
(defclass point () ((x 0) (y 0)) (:accessors-with-prefix point-))
(defmethod move ((p point) dx dy)
(with-slots (p) ;; p is known to be a point from the method-signature
(setq x (+ x dx) y (+ y dy))))
(with-slots ((p :direct t)) (setq x (+ x dx) y (+ y dy))))
(defmethod make-same-height ((p1 point) (p2 point))
;;; set the y coord of p1 to the y of p2, its reference.
;;; slots of p1 are accessed using the slot names
;;; slots of p2 are accessed using ref-<slot-name>
(with-slots (p1 (p2 :prefix ref-)) (setq y ref-y)))
(defmethod make-horizontal ((l line))
(let ((left (left-point l)) (right (right-point l)))
(with-slots ((left :class point :prefix left-)
(right :class point :prefix right-))
(setq left-y right-y))))
∂18-Sep-86 1306 Owners-CommonLoops.pa@Xerox.COM common loops for franz
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 13:06:52 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 18 SEP 86 11:41:26 PDT
Return-Path: <frodo@faraday.ECE.CMU.EDU>
Received: from faraday.ECE.CMU.EDU by Xerox.COM ; 18 SEP 86 11:36:26 PDT
Received: by faraday.ECE.CMU.EDU (4.12/4.7)
id <AA04222 frodo>; Thu, 18 Sep 86 14:24:16 edt;
Date: Thu, 18 Sep 86 14:24:16 edt
From: Ted Kowalski <frodo@faraday.ECE.CMU.EDU>
Message-Id: <8609181824.AA04222@faraday.ECE.CMU.EDU>
To: CommonLoops.pa@Xerox.COM
Subject: common loops for franz
Cc: Gregor.pa@Xerox.COM
the readme.tx file mentions a excl, but I didn't find one in /pub/pcl
does it exist?
thanks
∂18-Sep-86 1724 RPG Proposed Goals (Statement for OOPSLA)
∂18-Sep-86 1100 Owners-commonloopscore↑.pa@Xerox.COM Proposed Goals (Statement for OOPSLA)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 10:59:02 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 18 SEP 86 10:02:49 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 18 SEP 86
10:02:32 PDT
Date: 18 Sep 86 10:01 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: Proposed Goals (Statement for OOPSLA)
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860918-100249-8718@Xerox>
Sonya's improvements are generally good. I changed her original
sentence
``We will produce a portable implementation by evolving Portable
Common Loops...''
because it can parse in a funny way if you use a slightly less primary
definition of `evolve' than `to exhibit or produce through evolution.'
The definition is `to emit' as in `to evolve gases.' I parsed it as
it would appear in this sentence:
``Danny Bobrow ate a large plate of refried beans last night, went
back to PARC, and accidentally evolved Portable Common Loops. He
apologized profusely for his bad manners.''
Your rephrasing is better than mine, but it does commit Xerox to doing
the work of updating PCL, which they may elect not to do.
One reason for the phrasing of the pedigree paragraph is to emphasize
that the influence of New Flavors on CommonLoops has been going on for
over a year, and that the proposed standard will be more nearly along
the line of evolution, if you will, of CommonLoops as influenced by
New Flavors than a fresh merging of the two systems off the lines of
either. That is, the proposed standard will not be especially like
the CommonLoops of a year ago, but it will be very much like the
CommonLoops of today, because a movement towards New Flavors has
already taken place.
The reason for wanting to reason this way is to give the community
some sense of continuity over the past year. People will possibly rest
more comfortably if they believe that the ideas have developed over a
year's time rather than over a month's time.
The proposed standard will be what it will be, and its pedigree will
be of interest only to historians, and those historians will be able
to see the family lines accurately.
-rpg-
∂18-Sep-86 1724 RPG DEFCLASS should replace DEFSTRUCT
∂18-Sep-86 1100 Owners-commonloopscore↑.pa@Xerox.COM DEFCLASS should replace DEFSTRUCT
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 10:59:08 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 18 SEP 86 10:16:46 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 18 SEP 86
10:16:32 PDT
Date: 18 Sep 86 10:16 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: DEFCLASS should replace DEFSTRUCT
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860918-101646-8740@Xerox>
I bow to those who use mailers that sort mail according to subject:
My message is responsive to the discussion which has gone on under
this subject line, but the contents of my remarks and of the remarks
to which I reply bear no semantic relationship to the subject line.
There indeed was a simplicity in the early CommonLoops proposal, but the
simplicity was the simplicity of a naive proposal. In particular, the
use of Defmethod as a vague replacement for Defun to create a cloud of
functions that are invoked variously misses the goal of a clearly understood
construct. What precisely is the contract between this cloud and the outside
world? How does this cloud relate to Lisp functions? If you can FUNCALL this
cloud, can you affect it by affecting the thing that sits in the symbol-function
cell of a symbol? Simply stated, is the cloud a first-class object, or is it
like the heap?
The `negotiating' group is doing more than negotiating: It is attempting to
bring some design sense into the picture. The early CommonLoops proposal
was more like a slogan than a well-designed system.
-rpg-
∂18-Sep-86 2312 Masinter.pa@Xerox.COM Re: The name of WITH
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 23:12:08 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 18 SEP 86 13:25:33 PDT
Date: 18 Sep 86 13:23 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: The name of WITH
In-reply-to: Bobrow.pa's message of 18 Sep 86 08:28 PDT
To: Bobrow.pa@Xerox.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860918-132533-897@Xerox>
I think that under a with/with-slots/with-instances that programmers
should be encouraged (required?) to use SETF instead of SETQ to modify
slots.
(defmumble move-to ((p point) new-x new-y)
(with-slots (p)
(setf x new-x)
(setf y new-y)))
even though setq will "do".
I think the "prefix" option was added as a "fix" to the possibility of
conflicting slot names, and that the cure is worse than the disease. If
there's conflict, use the accessor functions instead.
(defmumble move-to-point ((p point) (p2 point))
(with-slots (p)
(setf x (point-x p2))
(setf y (point-y p2))))
∂18-Sep-86 2312 Owners-CommonLoops.pa@Xerox.COM FTP problems.
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 23:12:21 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 18 SEP 86 13:44:38 PDT
Return-Path: <ALarson.SoftTech@HI-MULTICS.ARPA>
Received: from HI-MULTICS.ARPA by Xerox.COM ; 18 SEP 86 13:42:04 PDT
Date: Thu, 18 Sep 86 15:31 CDT
From: ALarson@HI-MULTICS.ARPA
Subject: FTP problems.
To: CommonLoops.pa@Xerox.COM
Message-ID: <860918203156.583664@HI-MULTICS.ARPA>
I recently attempted to FTP the PCL software from PARCVAX.xerox.com, and
had much difficulty. Specifically the last 500-2K bytes of most of the
files were not transferred (at least not received). The system
administration people at my site (A large Multics) say no one else has
experienced the same trouble and suggested that I find out if anyone
else trying to get the software was having difficulty. So, did anyone
else have any trouble FTPing the code?
The following is a partial transcript of the FTP session:
The first line below is a DIR, the next two are GETs (of course the first
one worked correctly as predicted by Murphy).
Aaron.
----------------------------------------
user←ftp: -rw-r--r-- 1 270 41 10366 May 30 11:01 defsys.l
user←ftp: 150 Opening data connection for defsys.l (10.1.0.94,62250) (10366 bytes).
226 Transfer complete.
Total elapsed time: 27.6 seconds.
10366 bytes transferred in 24.4 seconds (3343 bits/sec).
user←ftp:
user←ftp: 150 Opening data connection for defsys.l (10.1.0.94,43178) (10366 bytes).
226 Transfer complete.
Total elapsed time: 30.7 seconds.
10224 bytes transferred in 25.5 seconds (3150 bits/sec).
user←ftp:
∂18-Sep-86 2312 Masinter.pa@Xerox.COM Re: DEFCLASS should replace DEFSTRUCT
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 23:12:34 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 18 SEP 86 13:48:55 PDT
Date: 18 Sep 86 13:47 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: DEFCLASS should replace DEFSTRUCT
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 18 Sep 86
10:16 PDT
To: RPG@SAIL.STANFORD.EDU
cc: commonloopscore↑.pa@Xerox.COM
Message-ID: <860918-134855-900@Xerox>
Having missed the early discussions of what ambiguity lies in the
original specification, I am forced to repeat the questions and hope
that you will have the patience to repeat the replies. If it is any
consolation, I think you will have to repeat this with others who might
have liked the spec, and suggest, if you have not done so, save your
replies.
To address your particular concerns:
"In particular, the use of Defmethod as a vague replacement for Defun to
create a cloud of
functions that are invoked variously misses the goal of a clearly
understood construct. What precisely is the contract between this cloud
and the outside world? "
What precisely is the contract between an ordinary function and the
outside world?
The specification of the behavior of a set of methods is no less defined
than the specification of what functions, macros and special forms do in
Common Lisp.
"How does this cloud relate to Lisp functions?"
It is different from any lisp function.
"If you can FUNCALL this cloud, can you affect it by affecting the thing
that sits in the symbol-function cell of a symbol? "
You cannot FUNCALL a cloud. You can FUNCALL a symbol and a function
object. A set of methods is neither. Perhaps you are asking the more
precise question:
"After (defmethod move ((x point) dx dy) ...), what does
(symbol-function 'move) return?"
I would answer that the answer belongs in the standard as much as the
question
"After (defmacro mood (x dx dy) ...), what does (symbol-function 'mood)
return?"
on which Common Lisp the Language is silent.
I think that your characterization of the early CommonLoops proposal as
"more like a slogan than a well-designed system." is incorrect, and even
more perjorative than the characterization of Common Lisp as "more like
a treaty than a specification."
∂18-Sep-86 2313 Owners-CommonLoops.pa@Xerox.COM Re: common loops for franz
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 23:13:29 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 18 SEP 86 15:35:09 PDT
Return-Path: <dcmartin@ingres.Berkeley.EDU>
Received: from ingres.Berkeley.EDU ([128.32.156.105]) by Xerox.COM ; 18
SEP 86 15:32:59 PDT
Received: by ingres.Berkeley.EDU (5.53/1.2)
id AA28636; Thu, 18 Sep 86 14:38:01 PDT
Message-Id: <8609182138.AA28636@ingres.Berkeley.EDU>
From: "David C. Martin" <dcmartin@ingres.Berkeley.EDU>
Office: 440 Evans - x2-9585
Home: 2441 Haste St #37, Berkeley, CA 94704 - (415) 843-6470
Fortran: is not backward, NARTROF is backwards.
To: Ted Kowalski <frodo@faraday.ece.cmu.edu>
Cc: CommonLoops.pa@Xerox.COM, Gregor.pa@Xerox.COM
Precedence: priority-mail
In-Reply-To: Your message of Thu, 18 Sep 86 14:24:16 edt
Subject: Re: common loops for franz
Date: 18 Sep 86 14:37:58 PDT (Thu)
Sender: dcmartin@ingres.Berkeley.EDU
Yeah, there should be... I am running it w/ Franz ExCl and I last updated
on 8/28 from parcvax. If you would like, I can make it publically ftp'able
from my VAX. We have also added the make-specializable feature to the
Franz implementation.
dcm
∂18-Sep-86 2313 Masinter.pa@Xerox.COM Re: FTP problems.
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 23:13:12 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 18 SEP 86 15:00:48 PDT
Date: 18 Sep 86 14:56 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: FTP problems.
In-reply-to: ALarson@HI-MULTICS.ARPA's message of Thu, 18 Sep 86 15:31
CDT
To: ALarson@HI-MULTICS.ARPA
cc: CommonLoops.pa@Xerox.COM, VaxcSystem↑.pa@Xerox.COM
Message-ID: <860918-150048-907@Xerox>
parcvax has been having hiccups with a new version of Unix. I'm not sure
they've been resolved yet, will keep you posted.
∂18-Sep-86 2313 Bobrow.pa@Xerox.COM Re: Proposed Goals (Statement for OOPSLA)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Sep 86 23:12:56 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 18 SEP 86 14:11:59 PDT
Date: 18 Sep 86 14:13 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: Proposed Goals (Statement for OOPSLA)
To: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860918-141159-904@Xerox>
In reading over these messages, I realized that what we were doing was
not describing technical goals and history, but setting up marketing
positions for corporations. I (and Gregor) are not in any position to
negotiate statements that have that kind of implication, and this
discussion is not appropriate for this list. Instead, let's continue
discussions of the important technical issues we need to resolve.
-- danny
∂19-Sep-86 0806 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Summary of features we all agree on
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 19 Sep 86 08:06:27 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 19 SEP 86 08:04:35 PDT
Return-Path: <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 19 SEP 86 08:03:52 PDT
Received: from JUNCO.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 107881; Fri
19-Sep-86 10:57:38 EDT
Date: Fri, 19 Sep 86 10:55 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Summary of features we all agree on
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.PA@Xerox.COM
In-Reply-To: <860910003916.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <860919105557.2.SKEENE@JUNCO.SCRC.Symbolics.COM>
Line-fold: No
Date: Wed, 10 Sep 86 00:39 EDT
From: David A. Moon <Moon@SCRC-STONY-BROOK.ARPA>
Date: 5 Sep 86 18:49 PDT
From: Bobrow.pa@Xerox.COM
class-name is a non-null symbol that names the class being
defined. If a class is already defined with this name, this
definition replaces the old definition. The default
meta-class ensures that when the definition of a class
changes, each existing instance of the class is updated to the
new format the next time it is accessed.
Each slot-spec is one of:
slot-name a non-null symbol.
(slot-name initial-value-form)
(slot-name slot-option...)
Each slot-option is an option name followed by its value.
The defined slot-options and their arguments are:
= initial-value-form
This an alternate way for providing a default
initial value form.
By the way I'm not wedded to the name "=". I couldn't think of
a clearer name when I tried for a few minutes, but perhaps
someone else can.
The name "=" seems inappropriate here.
How about :initial-value? Other possibilities: :default-value,
:default-initial-value, :initial-contents.
:accessor generic-function-name
Specifies that a function named generic-function-name
be automatically generated, to read the value of this
slot. SETF may be used with generic-function name to
write the value of the slot.
OK. If generic-function-name is NIL then this is a NOOP.
Specified so programs can generate these.
:reader generic-function-name
Specifies that a function named generic-function-name
be automatically generated, to read the value of this
slot.
We have called this :read-accessor.
I think users would find the distinction between :read-accessor
and :accessor confusing. Perhaps we need some more opinions
here, it's a difficult judgement.
The important distinction that these names have to imply is that one
generic function can read and write, while the other can only read.
The name :read-accessor is confusing. It implies that the generic
function is capable of both reading and accessing.
The names :accessor and :read-accessor do not go together well. If
we are going to use :reader-accessor, the appropriate companion option
should be named :read-and-write-accessor. That way the user
understands that :read-and-write-accessor does more than :read-accessor.
I prefer the names :accessor and :reader because they really describe
what the generic function can do. The one generated by :ACCESSOR has
the capability of ACCESSING (both reading and being used with SETF).
The one generated by :READER has the capability of READING.
We specify that if this is
given, then SETF may NOT be used with this accessor. If
generic-function-name is NIL then this is a NOOP.
Agreed.
∂19-Sep-86 0944 Bobrow.pa@Xerox.COM Re: Summary of features we all agree on
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 19 Sep 86 09:44:08 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 19 SEP 86 09:37:30 PDT
Date: 19 Sep 86 09:37 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Summary of features we all agree on
In-reply-to: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 19 Sep 86 10:55 EDT
To: skeene@STONY-BROOK.SCRC.Symbolics.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, CommonLoopsCore↑.PA@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <860919-093730-1229@Xerox>
The important distinction that these names have to imply is
that one generic function can read and write, while the other can
only read.
The name :read-accessor is confusing. It implies that the
generic function is capable of both reading and accessing.
The names :accessor and :read-accessor do not go together well.
If we are going to use :reader-accessor, the appropriate companion
option should be named :read-and-write-accessor. That way the
user understands that :read-and-write-accessor does more than
:read-accessor.
I prefer the names :accessor and :reader because they really
describe what the generic function can do. The one generated by
:ACCESSOR has the capability of ACCESSING (both reading and being
used with SETF). The one generated by :READER has the capability of
READING.
I like this choice of names, :accessor and :reader.
-- danny
∂19-Sep-86 1132 Owners-CommonLoopsCore↑.PA@Xerox.COM Re: Summary of features we all agree on
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 19 Sep 86 11:31:55 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 19 SEP 86 10:42:24 PDT
Return-Path: <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 19 SEP 86 10:42:02 PDT
Received: from JUNCO.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 108123; Fri
19-Sep-86 13:40:40 EDT
Date: Fri, 19 Sep 86 13:38 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Summary of features we all agree on
To: Moon@STONY-BROOK.SCRC.Symbolics.COM, bobrow.pa@Xerox.COM
cc: CommonLoopsCore↑.PA@Xerox.COM
In-Reply-To: <860910003916.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <860919133856.4.SKEENE@JUNCO.SCRC.Symbolics.COM>
Line-fold: No
Date: Wed, 10 Sep 86 00:39 EDT
From: David A. Moon <Moon@SCRC-STONY-BROOK.ARPA>
Date: 5 Sep 86 18:49 PDT
From: Bobrow.pa@Xerox.COM
This is from the section on DEFCLASS slot-options.
:allocation
:allocation can have values
:instance (allocated in the instance),
:class (storage allocated in the class and shared by all
instances),
:dynamic (storage allocated in the instance on first use
(like Flavors Proplist mixin)
:none expect accessor methods for this to be defined for
this slot in this class
We need to discuss which of these allocation options belong in
the standard. Maybe only a subset of them.
This is the last I've heard (read) of :allocation. Maybe it's time to
start discussing the :allocation options again. I've elaborated on
Danny's write-up above with some information from the CommonLoops paper,
and added one thing. For :dynamic, I assume that if you initialize
the slot with a keyword argument to MAKE-INSTANCE, the slot gets
allocated right then. True?
Also, would you clarify what you meant by:
:none expect accessor methods for this to be defined for
this slot in this class
---------------------------------------------------------------------
:allocation keyword
Specifies where storage is allocated for this slot. The keyword can
be one of these:
:instance Storage is allocated in the instance itself; each
instance has its separate value for this slot. This
is the default.
:class Storage is allocated in the class. Thus a single
value for this slot is shared by all instances.
:dynamic Storage is allocated in the instance at the time of
the first use of the slot. If the slot is initialized
with a keyword argument to MAKE-INSTANCE, the slot is
allocated then. If the first access is a read, then
storage is allocated and the default value declared
in the DEFCLASS, if any, is stored in the slot and
returned. If the first access is a SETF, then storage
is allocated and the value is stored in the slot and
returned. This option allows infrequently-used slots
to take storage only when necessary.
:none No storage is to be allocated; the slot should not
exist in instances of this class. This is used to
override inheritance of slots defined by a
super-class.
∂19-Sep-86 1132 Kahn.pa@Xerox.COM Short names like MAKE
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 19 Sep 86 11:32:02 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 19 SEP 86 10:45:24 PDT
Date: 19 Sep 86 10:37 PDT
Sender: Kahn.pa@Xerox.COM
Subject: Short names like MAKE
To: CommonLoopsCore↑.pa@Xerox.COM
cc: Kahn.pa@Xerox.COM
From: Ken Kahn <Kahn.pa@Xerox.COM>
Message-ID: <860919-104524-1315@Xerox>
I've hesitated to bring this up since it seems that everyone is happy
with the change from MAKE to MAKE-INSTANCE. I'm not.
I think short names are appropriate when something is used frequently
enough. I'm glad LET isn't called LET-VARIABLES, CONS isn't called
MAKE-CONS etc. My expectation is that all user defined data structures
will be created by MAKE(-INSTANCE) and that programs frequently do
create structures. To put it more extremely than I really believe --
The only things that programs will make will be made by MAKE or by
existing primitive type creation functions (CONS, MAKE-ARRAY...)
I feel less strongly about WITH vs WITH-INSTANCE since I don't really
know how often people will be using it explictly.(Btw, I like Moon's
WITH keyword syntax for dealing with prefix, class etc. though I also
share Larry's concern that the cases where they will be used are rare
enough that the added complexity isn't worth it.)
----- ken
∂20-Sep-86 1132 Owners-commonloopscore↑.pa@Xerox.COM Short Names
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 20 Sep 86 11:31:59 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 20 SEP 86 10:36:38 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 20 SEP 86
10:36:27 PDT
Date: 20 Sep 86 10:36 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: Short Names
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860920-103638-2050@Xerox>
It is tempting to want to use short names for things that are imagined to
be used frequently. People designing an object-oriented programming
language feel that the primitives they define will be the ones frequently
used. Recall that in the overall age of Lisp, CommonLoops has hardly
any history. Moreover, because the designer of it feels that his primitives
are the right ones, perhaps a second-generation CommonLoops hacker
will feel that some different primitives are right.
In Common Lisp we decided to not use up many of the `good' names
or characters so that users could have them. Exceptions are time-honored
Lisp names, such as LET and CONS.
If you choose a long name for MAKE-INSTANCE, then the user can
macro-ify it to a short name. If you choose a short, nice name
like MAKE, no one else can use it. That is, the long name is
the safe choice.
Also, do you suppose that your choice of the meaning of an
English word like MAKE for a technical operation is better than
what a real programmer would want to choose as the meaning?
I strongly object to using names that are likely to be of use to
programmers to name operations that are meaningful in his application.
-rpg-
∂21-Sep-86 1230 masinter.PA@Xerox.COM mutable vs immutable generic functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 86 12:30:09 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 86 12:27:06 PDT
From: masinter.PA@Xerox.COM
Date: 21 Sep 86 12:26:49 PDT
Subject: mutable vs immutable generic functions
To: commonloopscore↑.pa@Xerox.COM, pavel.PA@Xerox.COM,
nuyens.PA@Xerox.COM, sybalsky.PA@Xerox.COM
Message-ID: <860921-122706-1235@Xerox>
(This note came out of a design review meeting with some of the Common
Lisp implementors here. )
This is very condensed form of the arguments:
The question is: are Generic Functions mutable or immutable objects?
Example:
(defmethod foo ((a widget)) .1.)
(setq foofn #'foo)
(defmethod foo ((a warble)) .2.)
(funcall foofn (make-warble) ...)
Mutable:
defmethod, add-method, remove-method, etc. destructively modify the
generic function to include the new method. In the example, the funcall
will get definition .2..
Immutable:
Generic functions are still objects that can be passed around, sent to
FUNCALL, etc. However, they are immutable. add-method, remove-method
merely return a {it new} generic function with the specified method
added or removed. In the example, the funcall will get a generic
function which does *not* see the defmethod.
defmethod merely replaces symbol-function with a new generic function.
Unspecified:
The standard doesn't say. Implementations are free to choose. It is an
error to rely upon what happens.
Pro & Cons:
mutable vs immutable:
mutable better than immutable:
Mutable is a powerful feature. It is consistent with the current
implementation of PCL. (This is what's written in the documentation that
I have.) Mutable allows more efficient method-definition than immutable.
Immutable is better than mutable:
Mutable is too powerful a feature. It allows programs to do things they
shouldn't be able to do). Mutable is inconsistent with the use of
functions elsewhere in Common Lisp. (A program could, when handed a
function, remove all of its methods and insert a "default
implementation" of its own choosing).
Unspecified vs specified:
spec it: Programs that depend on one behavior vs the other will be
difficult to port if left unspecified.
don't spec it: Many programs won't care, and leaving it unspecified will
allow greater implementation freedom. If we can't agree, we will have to
leave it unspecified.
∂21-Sep-86 1355 Bobrow.pa@Xerox.COM Syntax of DEFCLASS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 86 13:55:11 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 86 13:51:48 PDT
Date: 21 Sep 86 13:51 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Syntax of DEFCLASS
To: CommonLoopsCore↑.pa@Xerox.COM
cc: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <860921-135148-1298@Xerox>
In an internal design review at Xerox of the current state of the
specification, strong arguments were presented why defclass should have
a syntax parallel to that of defstruct. These were:
1) Learnability -- Currently people know that syntax. Simple variations
ae easier to learn than extensive ones.
2) Documentation -- Current documentation of defstruct could be used in
large part to document defclass. This makes the book stay smaller. It
makes all books written about Common Lisp have to say less.
3) Elimination of defstruct from the language -- If the syntax is
similar, and the transformation from defstruct to defclass forms is
straightforward, it will be easier to argue for the removal of
defstruct. (Creation of structures and use of :type might be replaced
by use of the :metaclass option.)
The major problem with using defstruct synatx for defclass seems to be
figuring out how to avoid having two conflicting sets of options
depending on the :metaclass.
In particular, the current :accessors-with-prefix defclass option is
different than the :conc-name option.
Other, less significant options which cause problems are
:initable-slots, :initialize-only vs. :read-only and :init-keywords.
-- danny
∂21-Sep-86 1433 Owners-CommonLoopsCore↑.PA@Xerox.COM mutable vs immutable generic functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 86 14:33:07 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 21 SEP 86 14:32:30 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 21 SEP 86 14:32:05 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 109234; Sun
21-Sep-86 17:30:25 EDT
Date: Sun, 21 Sep 86 17:29 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: mutable vs immutable generic functions
To: CommonLoopsCore↑.PA@Xerox.COM
cc: masinter.PA@Xerox.COM, pavel.PA@Xerox.COM, nuyens.PA@Xerox.COM,
sybalsky.PA@Xerox.COM
In-Reply-To: <860921-122706-1235@Xerox>
Message-ID: <860921172940.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 21 Sep 86 12:26:49 PDT
From: masinter.PA@Xerox.COM
The question is: are Generic Functions mutable or immutable objects?
Example:
(defmethod foo ((a widget)) .1.)
(setq foofn #'foo)
(defmethod foo ((a warble)) .2.)
(funcall foofn (make-warble) ...)
Mutable:
defmethod, add-method, remove-method, etc. destructively modify the
generic function to include the new method. In the example, the funcall
will get definition .2..
Immutable:
Generic functions are still objects that can be passed around, sent to
FUNCALL, etc. However, they are immutable. add-method, remove-method
merely return a {it new} generic function with the specified method
added or removed. In the example, the funcall will get a generic
function which does *not* see the defmethod.
defmethod merely replaces symbol-function with a new generic function.
Unspecified:
The standard doesn't say. Implementations are free to choose. It is an
error to rely upon what happens.
Pro & Cons:
mutable vs immutable:
mutable better than immutable:
Mutable is a powerful feature. It is consistent with the current
implementation of PCL. (This is what's written in the documentation that
I have.) Mutable allows more efficient method-definition than immutable.
Immutable is better than mutable:
Mutable is too powerful a feature. It allows programs to do things they
shouldn't be able to do). Mutable is inconsistent with the use of
functions elsewhere in Common Lisp. (A program could, when handed a
function, remove all of its methods and insert a "default
implementation" of its own choosing).
Unspecified vs specified:
spec it: Programs that depend on one behavior vs the other will be
difficult to port if left unspecified.
don't spec it: Many programs won't care, and leaving it unspecified will
allow greater implementation freedom. If we can't agree, we will have to
leave it unspecified.
Your arguments make sense to me, and I firmly believe that it should be
unspecified. Here's why:
In New Flavors the interaction between doing #'foo and adding or
removing a method of foo varies depending on factors that the user might
not be able to predict easily. This is because there are multiple
implementations of what PCL calls discriminating functions, and
depending on which implementation Flavors happens to choose the result
of #'foo might capture some or all of the current set of methods or
might be independent of the current set of methods. I imagine that on
stock-hardware this implementation freedom would be even more important,
if high performance was a goal. In your terminology, generic functions
in New Flavors are sometimes mutable, sometimes immutable, and sometimes
partially mutable.
This has not bothered any programmers, as far as I know, in the 9 or 10
months that New Flavors has been in use. This shouldn't surprise us,
since ordinary functions behave similarly. Consider these examples:
[1] (defun foo (...)
...
(foo-1...))
(defun foo-1 (...)
...)
[2] (defun foo (...)
(flet ((foo-1 (...) ...))
...
(foo-1...)))
Suppose someone does #'foo and saves it away, and then a second someone
redefines foo-1, an internal function of foo whose existence is not known
to the first someone. In example 1, the behavior of the saved-away foo
changes, in example 2 it stays the same, yet as far as the contract of
the function foo is concerned these two ways of implementing its
internal function are equivalent.
Depending on one's taste, one could say this shows that Common Lisp does
not have a well-defined semantics, or one could say that this is just an
example of the way that, in Lisp, copying the value of a variable
doesn't copy the object, just the reference to the object. Either way,
I think it makes sense for generic functions to have the same freedom of
behavior when their internal subroutines are changed that ordinary
functions enjoy.
∂21-Sep-86 1529 Owners-CommonLoopsCore↑.pa@Xerox.COM Syntax of DEFCLASS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 86 15:29:14 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 21 SEP 86 15:22:58 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 21 SEP 86 15:22:33 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 109241; Sun
21-Sep-86 18:21:05 EDT
Date: Sun, 21 Sep 86 18:20 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Syntax of DEFCLASS
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860921-135148-1298@Xerox>
Message-ID: <860921182022.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 21 Sep 86 13:51 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
In an internal design review at Xerox of the current state of the
specification, strong arguments were presented why defclass should have
a syntax parallel to that of defstruct. These were:
I thought we had been through this already. I'll see if I can reconstruct
the arguments that lead to the decision not to use the defstruct syntax.
1) Learnability -- Currently people know that syntax. Simple variations
ae easier to learn than extensive ones.
This is true, but on the other hand the syntax of defstruct is not
consistent with the syntax of anything else. In any case this is hardly
likely to be the part that newcomers to object-oriented programming find
the most difficult to learn.
2) Documentation -- Current documentation of defstruct could be used in
large part to document defclass. This makes the book stay smaller. It
makes all books written about Common Lisp have to say less.
This is true, but the percentage decrease in the description of
object-oriented programming would be quite small.
3) Elimination of defstruct from the language -- If the syntax is
similar, and the transformation from defstruct to defclass forms is
straightforward, it will be easier to argue for the removal of
defstruct. (Creation of structures and use of :type might be replaced
by use of the :metaclass option.)
This is true, but not compelling. Defstruct could be removed from the
language regardless of whether the syntax is similar, as long as a given
defstruct form can be mechanically translated into an equivalent defclass
form.
The major problem with using defstruct synatx for defclass seems to be
figuring out how to avoid having two conflicting sets of options
depending on the :metaclass.
In particular, the current :accessors-with-prefix defclass option is
different than the :conc-name option.
Other, less significant options which cause problems are
:initable-slots, :initialize-only vs. :read-only and :init-keywords.
I don't think these are the main problems at all. The real problem with
defstruct is that it was designed nine years ago, is not consistent with
current ideas of easy-to-understand syntax for defining forms, and is
a gross kludge. Rather than perpetuate this wart on the language, we
ought to be replacing it with something better. Requiring compatibility
with defstruct is requiring compatibility with the mistakes of the past,
and in my opinion would seriously impair the understandability and
usability of the object-oriented programming facility for only small
gains. All of the arguments above are true, but I think they are much
too weak to outweigh the problems of defstruct. Here are some specifics:
The original syntax of defstruct didn't allow for options, so they had
to be added by a kludge -- replacing the name with a list of the name
and options. The original syntax of defstruct didn't allow for
documentation, so it had to be added by another kludge -- using a string
instead of a slot name. Slot-options had to be added by yet a third
kludge, which requires that an initialization form be specified whether
or not it is desired in order to specify slot-options. The format of
slot-options is not consistent with the format of regular options
(admittedly the currently proposed DEFCLASS has the same problem, and it
appears to be difficult to fix). The format of the :INCLUDE option does
not admit straightforward extension to multiple superclasses; one kludge
or another is required to get around this.
Defstruct contains violations of abstraction or modularity; it has no
concept of a separation between the implementation of a structure (or
class) and clients of that structure or class. For example, all slots
can be initialized to arbitrary values when constructing a structure;
this ought to be under the control of the implementation of the
structure. Similarly, the ability of the implementation of a structure
to modify a slot is not separated from the ability of the clients to do
so.
The default values for the :CONC-NAME, :CONSTRUCTOR, :COPIER, and
:PREDICATE options are inappropriate. (Perhaps not everyone agrees that
all of these are inappropriate, but the existence of controversy is
sufficient reason by itself to reconsider these defaults.) If the
object-oriented facility is an extension of DEFSTRUCT, it would be
forced to make the same inappropriate choices for the sake of
compatibility.
Given all of these problems, a clean break with the past is a better
choice than trying to maintain compatibility with a kludge. Of course
defstruct cannot be removed immediately, because one does not make
sudden incompatible changes to a language that thousands of people are
using, but the long-term plan should be to phase out defstruct once
a replacement has been accepted as a standard.
∂21-Sep-86 1537 MASINTER.PA@Xerox.COM (change-class x y) => (setf (class-of x) y)?
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 86 15:37:30 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 86 15:35:27 PDT
From: MASINTER.PA@Xerox.COM
Date: 21 Sep 86 15:34:29 PDT
Subject: (change-class x y) => (setf (class-of x) y)?
To: commonloopscore↑.PA@Xerox.COM
cc: nuyens.PA@Xerox.COM, sybalsky.PA@Xerox.COM, pavel.PA@Xerox.COM
Message-ID: <860921-153527-1339@Xerox>
There doesn't seem to be any apparent reason to make change-class a
separate "thing", rather than a notation that class-of is setf-able for
some kinds of objects.
Opinions?
∂21-Sep-86 1540 Bobrow.pa@Xerox.COM Generic Function Objects
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 86 15:39:59 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 86 15:39:30 PDT
Date: 21 Sep 86 15:39 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Generic Function Objects
To: CommonLoopsCore↑.pa@Xerox.COM
cc: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Message-ID: <860921-153930-1345@Xerox>
In the existing CommonLoops papers and code, there is an object called
the discriminator and piece of code called the discriminating function.
The discriminating function was stored inside the discriminator, and
when the discriminator was "named", was also stored in the
symbol-function cell of the symbol which named the discriminator. The
discriminating-function was the thing you funcalled, the discriminator
was the thing that you passed to add-method.
A potentially better design combines the discriminator and the
discriminating function into a single, closure-like, object called the
generic function. The generic function is funcallable; funcalling it
causes method lookup to happen. Accessors which used to work on the
discriminator work directly on the generic function. In particular,
generic-function-methods returns a list of all the methods defined on a
generic function.
Generic functions are mutable, and are side-effected by add-method and
remove-method. An alternative proposal makes them immutable, add-method
and remove-method return new generic-functions, see Masinter's message
of 21-Sep-86 12:26:49 PDT.
We spent a fair amount of time discussing the implementation
implications of this. We believe that this does not cause serious
implementation problems. At least the mutable case can even be
implemented fairly efficiently in PCL.
This new scheme has not yet been discussed on this list though. This
message is intended to spark that discussion.
-- danny, Gregor
∂21-Sep-86 1553 MASINTER.PA@Xerox.COM make vs make-instance
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 86 15:53:15 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 86 15:51:01 PDT
From: MASINTER.PA@Xerox.COM
Date: 21 Sep 86 15:50:46 PDT
Subject: make vs make-instance
To: commonLoopsCore↑.PA@Xerox.COM
Message-ID: <860921-155101-1347@Xerox>
The CommonLoops paper used only two short names, viz "make" and "with".
"make" was chosen, not so much because it is frequently typed and thus
needs to be short, but rather in conformance with the Common Lisp style
in defstruct, namely that
(make-ship :a 3 :b 17)
seemed like a simple step away from
(make 'ship :a 3 :b 17)
and is further away from
(make-instance 'ship :a 3 :b 17).
If it is any help, make-instance is also incompatible with having a
structure named "instance", which seems as likely to me at the moment as
the user having a function or macro named "make".
∂21-Sep-86 1615 Bobrow.pa@Xerox.COM Re: (change-class x y) => (setf (class-of x) y)?
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 86 16:08:24 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 86 16:05:03 PDT
Date: 21 Sep 86 16:03 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: (change-class x y) => (setf (class-of x) y)?
In-reply-to: MASINTER.PA's message of 21-Sep-86 15:34:29 PDT
To: MASINTER.PA@Xerox.COM
cc: commonloopscore↑.PA@Xerox.COM, nuyens.PA@Xerox.COM,
sybalsky.PA@Xerox.COM, pavel.PA@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <860921-160503-1357@Xerox>
(change-class x y) => (setf (class-of x) y)?
There doesn't seem to be any apparent reason to make
change-class a separate "thing", rather than a notation that
class-of is setf-able for some kinds of objects.
change-class is a sufficiently serious operation that having a separate
name is important. It does significantly more than simply set a field,
so (setf (class-of x) y) would be misleading to a user.
-- danny
∂21-Sep-86 1638 Kahn.pa@Xerox.COM Re: Short Names
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 86 16:38:52 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 86 16:34:16 PDT
Date: 21 Sep 86 16:34 PDT
Sender: Kahn.pa@Xerox.COM
Subject: Re: Short Names
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 20 Sep 86
10:36 PDT
To: RPG@SAIL.STANFORD.EDU
cc: commonloopscore↑.pa@Xerox.COM
From: Ken Kahn <Kahn.pa@Xerox.COM>
Message-ID: <860921-163416-1364@Xerox>
In Common Lisp we decided to not use up many of the `good' names
or characters so that users could have them. Exceptions are
time-honored Lisp names, such as LET and CONS.
Skimming the index of the Silver book reveals the following short names
which to my knowledge were not "time-honored Lisp names":
bit, block, byte, close, character, complex, count, describe, elt,
every, export, find, import, keyword, loop, merge, ...
----- ken
∂21-Sep-86 1717 Kahn.pa@Xerox.COM Re: (change-class x y) => (setf (class-of x) y)?
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 86 17:17:03 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 86 17:15:50 PDT
Date: 21 Sep 86 17:15 PDT
Sender: Kahn.pa@Xerox.COM
Subject: Re: (change-class x y) => (setf (class-of x) y)?
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 21 Sep 86 16:03 PDT
To: Bobrow.pa@Xerox.COM
cc: MASINTER.PA@Xerox.COM, commonloopscore↑.PA@Xerox.COM,
nuyens.PA@Xerox.COM, sybalsky.PA@Xerox.COM, pavel.PA@Xerox.COM
From: Ken Kahn <Kahn.pa@Xerox.COM>
Message-ID: <860921-171550-1381@Xerox>
I like Larry's suggestion for the same reasons that most people like
SETF -- fewer names to deal with.
change-class is a sufficiently serious operation that having a
separate name is important. It does significantly more than simply
set a field, so (setf (class-of x) y) would be misleading to a
user.
Its true that the implementation would do "significantly more than
simply set a field" but I fail to see why that misleads the user.
Consider in Common Lisp (SETF (MACRO-FUNCTION ...) ...) which in some
implementations causes a macro expansion cache to become invalidated
causing some hash tables to be cleared. How is the user "mislead" here?
Do you mean that in the two cases the user is likely to have a mistaken
performance model by using SETF? But (SETF (GET-SLOT ...) ..)
may cause arbitrary computation too.
----- ken
∂21-Sep-86 1725 Kahn.pa@Xerox.COM Re: default optional arguments to a generic function
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 86 17:25:08 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 86 17:23:57 PDT
Date: 21 Sep 86 17:23 PDT
Sender: Kahn.pa@Xerox.COM
Subject: Re: default optional arguments to a generic function
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 17 Sep 86 16:15 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
From: Ken Kahn <Kahn.pa@Xerox.COM>
Message-ID: <860921-172357-1384@Xerox>
(defun draw (thing &optional (place *draw-window*
place-supplied-p))
"Draw thing on place."
(draw-internal thing place place-supplied-p))
(defmethod draw-internal ((thing line) (place raster-display)
place-supplied-p) ...)
(defmethod draw-internal ((thing line) (place vector-display)
place-supplied-p) ...)
Flavors provides the feature that you don't have to make
up the auxiliary name draw-internal, which is confusing because
the externally visible interface is named draw but you put methods
on draw-internal. You do this by (translating out of the present
Flavors syntax, which is too biased against multimethods):
(defgeneric draw (thing &optional (place *draw-window*
place-supplied-p))
"Draw thing on place."
(:method-arguments thing place place-supplied-p)
(:function
(funcall (generic draw) thing place place-supplied-p)))
(defmethod draw ((thing line) (place raster-display)
place-supplied-p) ...)
(defmethod draw ((thing line) (place vector-display)
place-supplied-p) ...)
I liked your proposal until I started to imagine myself writing DRAW
methods and having to keep in my head that someone can call DRAW with 1
or 2 arguments but my methods have 3 required arguments. I find this
less confusing than the alternative of using DRAW-INTERNAL where "the
externally visible interface is named draw but you put methods on
draw-internal".
----- ken
∂21-Sep-86 1812 Bobrow.pa@Xerox.COM default optional arguments to a generic function
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 86 18:12:35 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 86 18:06:17 PDT
Date: 21 Sep 86 18:06 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: default optional arguments to a generic function
To: CommonLoopsCore↑.pa@Xerox.COM
cc: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <860921-180617-1396@Xerox>
The following principles seem to be ones we have agreed to with respect
to generic functions and methods.
1) Methods should be able to take any Common Lisp lambda-list. In
particular the default defmethod must be able to look like a defun.
2) defgeneric should be optional, unless special options are used, such
as :generic-function-class.
3) The contract of the generic function should be true for all methods,
and that contract should be computable from a defmethod form.
This seems to lead to two competing proposals (Gregor says I am
oversimplifying)
Proposal a) The generic function specifies the full argument list, and
all methods must have congruent argument lists. This leads to the
problem of defining congruence (Moon proposed some rules, but as
Masinter pointed out, they had a problem with renaming of variables used
in default value forms). It also leads to redundancy in the methods --
making it difficult to change a default value form in a single place.
However, Gregor favors this scheme as later extendible by removing
restrictions. He would allow methods to take extra keywrod args if
&allow-other-keys appears in the defgeneric.
Proposal b) The generic function specifies only the required arguments,
and methods discriminate only on those arguments. However, methods can
have arbitrary argument list beyond the required arguments. From any
method, the generic contract can be computed. All methods must have the
same number of min-args.
This allows cases 1a) and 1b)
Case 1a. "draw-line"
draw-line takes an optional, the width of the line in
device dependent units. Because they are device dependent
units, each individual method would like to default this
argument on its own.
(defmethod draw-line ((dev printer) p1 p2
&optional (width 7)) ...)
(defmethod draw-line ((dev window) p1 p2
&optional (width 1)) ...)
Case 1b.
Within case 1, some methods may want to take an extra
argument. Also see case 3 which is similar.
(defmethod draw-line ((d gray-display) p1 p2
&optional (width 3)
(gray *gray1*))
..)
Date: Wed, 17 Sep 86 16:15 EDT
From: David A. Moon
The problem here is that the generic function doesn't have a
consistent contract. The meaning, or even the existence, of one
argument depends on the class of another argument. I don't see how
a caller of draw-line could operate without knowing the exact
method that was going to be called. From experience I know it's
possible to have all sorts of arguments about whether this is good
or bad programming practice. In New Flavors, these arguments were
resolved in favor of consistency of contracts, rather than the
increased flexibility of different contracts for different methods,
but not everyone was happy.
I think it is possible to know that a method is coming from a particular
part of the class lattice (without knowing the exact method) and hence
know the local contract. Consistency of generic contract is only in the
required argument set.
To take care of GFD#2, I propose that we allow the generic to specify
optionals that it fills in. The contract between the generic and the
methods is to always supply these required method arguments. I claim it
should not be part of the contract between the generic and the method to
provide that information. I propose a lambda list keyword option
&generic-optional in the generic function. Optional argument
specifications after this provide only argument names and default value
forms, but cannot have a supplied-p variable.
For example:
(defgeneric draw (thing &generic-optional (place *draw-window*))
"Draw thing on place.")
(defmethod draw ((thing line) (place raster-display)) ...)
(defmethod draw ((thing line) (place vector-display)) ...)
Methods must have required arguments where generic-optionals are
provided. Optionals in methods cannot be discriminated on.
Case 3 "move" is outlawed by this proposal, because the number of
required arguments differ.
∂21-Sep-86 1925 Bobrow.pa@Xerox.COM Class Precedence List
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 86 19:25:29 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 86 19:19:28 PDT
Date: 21 Sep 86 19:19 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Class Precedence List
To: CommonLoopsCore↑.pa@Xerox.COM
cc: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>, Kahn.pa@Xerox.COM
Message-ID: <860921-191928-1425@Xerox>
A recursive rule that computes class precedence lists locally.
1) A class c1 cannot be given any super that has c1 in its
class-precedence list.
2) If c1 has one superclass c2, then the class precedence list of c1 is
(cons c1 (c-p-l c2))
3) If c1 has two superclasses, c2 and c3, then use
(cons c1 (merge-pls (c-p-l c2) (c-p-l c3))
where (merge-pls first second)
takes the prefix of first until it finds an element in common with
second.
If there is none, then use all of first. Follow by the prefix of second
up to the common element. If this has any element in common with the
rest of first, signal an error. Insert the common element. Repeat
until first is empty, then append the rest of second.
4) If there are more than 2, then merge the pairs in an associative
manner
The claim is that this algorithm produces lists that obey all of Moon's
rules, is local and one pass.
"Proof"
A class with no super obeys Moon's rules
Proceed by induction.
Clearly (1) Each class precedes it own supers
(2) Local ordering is preserved, since no ordering in the individual
lists is changed by the merge. And the first element of each sublist
(the local supers) have their order preserved.
(3) Duplicate elimination always puts things as early as they can go.
Several minutes thought has shown no problem with this.???
danny and ken
∂21-Sep-86 2233 MASINTER.PA@Xerox.COM initial class lattice
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 86 22:33:48 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 86 22:24:30 PDT
From: MASINTER.PA@Xerox.COM
Date: 21 Sep 86 22:24:10 PDT
Subject: initial class lattice
To: commonloopscore↑.PA@Xerox.COM
Message-ID: <860921-222430-1479@Xerox>
I had some questions about the initial class lattice for Common Lisp
types.
First, since Common Lisp doesn't require "compiled-function" or
"function" to be first-class, they can't be classes in the initial
hierarchy. (Recall that a compiled function is allowed to be a vector,
for example.)
Second, while "standard-char" is well defined, I don't think it should
be a class; I imagine it would otherwise be difficult to make (class-of
#\a) return something other than (class-of #\page).
Third, I don't think that bit, fixnum and bignum should be defined to be
part of the required class lattice, because they correspond conceptually
to "range" types.
Finally, for those items that have multiple superclasses, we need to
either defince an order or else remove one of the superclasses.
I like having "list" as a class, but the precidence for NIL needs to be
defined. I'd say that NIL was a symbol first and a list second, on the
basis that "list" is an abstraction but "symbol" is quite concrete, and,
at least when I write 'em, I tend to put the concrete classes before the
abstract ones.
As for simple-vector, simple-bit-vector, simple-string, my inclination
is that "simple" isn't a particularly interesting dimension to
discriminate on; removing "simple-array" would do most of the cleanup,
and saying that a "vector" is first an array and secondly a sequence
would finish it off.
(I'm typing this at a stupid dial-in mailer which doesn't allow me to
edit, so I'll add as an afterthought):
On further examination, there are no requirements that stream,
hash-table, readtable, package, pathname or random-state be distinct
from other types (p 33), and my belief is that these cannot then be
required to be "first class" classes, in that (class-of (make-hash-table
...)) might return the same as (class-of (make-array ...)) for suitable
arguments.
Perhaps this can be stated in the subjunctive, e.g. "if these are
distinct types in your Common Lisp implementation, they'll probably be
distinct classes in any implementation of this spec".
∂22-Sep-86 0123 MASINTER.PA@Xerox.COM another name for "run-super"
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 01:22:58 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 SEP 86 01:22:36 PDT
From: MASINTER.PA@Xerox.COM
Date: 22 Sep 86 1:22:20 PDT
Subject: another name for "run-super"
To: commonloopscore↑.PA@Xerox.COM
Message-ID: <860922-012236-1523@Xerox>
names matter, I guess.
There's no "run" in Common Lisp, and no "super" in CommonLoops. How about
call-next-method. (Or, if you want, apply-next-method).
∂22-Sep-86 0829 Owners-commonloopscore↑.PA@Xerox.COM another name for "run-super"
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 08:29:42 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 22 SEP 86 08:19:44 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.PA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 22 SEP 86 08:19:13 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 109619; Mon
22-Sep-86 11:17:24 EDT
Date: Mon, 22 Sep 86 11:16 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: another name for "run-super"
To: MASINTER.PA@Xerox.COM
cc: commonloopscore↑.PA@Xerox.COM
In-Reply-To: <860922-012236-1523@Xerox>
Message-ID: <860922111626.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 22 Sep 86 1:22:20 PDT
From: MASINTER.PA@Xerox.COM
call-next-method. (Or, if you want, apply-next-method).
Call-next-method is a better suggestion than mine: next-method.
If we were to add an extension to allow different arguments to be
substituted when calling the next method, both call-next-method
and apply-next-method would be necessary (one is like funcall,
the other is like apply), so I think these are good names.
∂22-Sep-86 0916 Owners-commonloopscore↑.PA@Xerox.COM initial class lattice
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 09:15:20 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 22 SEP 86 09:08:43 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.PA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 22 SEP 86 09:04:06 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 109670; Mon
22-Sep-86 12:01:47 EDT
Date: Mon, 22 Sep 86 12:00 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: initial class lattice
To: commonloopscore↑.PA@Xerox.COM
In-Reply-To: <860921-222430-1479@Xerox>
Message-ID: <860922120053.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 21 Sep 86 22:24:10 PDT
From: MASINTER.PA@Xerox.COM
I had some questions about the initial class lattice for Common Lisp
types.
I've been thinking about this also, but wasn't quite ready to mail out
my complete list yet. I'll give some comments now, though. In most
cases I agree with you.
First, since Common Lisp doesn't require "compiled-function" or
"function" to be first-class, they can't be classes in the initial
hierarchy. (Recall that a compiled function is allowed to be a vector,
for example.)
COMPILED-FUNCTION is allowed to inherit from VECTOR [does it say this in
CLtL someplace?], but it's still meaningful to ask "is this object a
compiled-function", so it should be meaningful to define a method that
applies if one of its arguments is a compiled-function. On the other
hand, the definition of the FUNCTION type (CLtL p.32) is so vague that
even though there is a FUNCTIONP function, I hesitate to say that it
should be meaningful to define a method that applies if one of its
arguments is a function. So I agree with you about FUNCTION, but
disagree on COMPILED-FUNCTION.
It is an interesting point that, although we can identify some classes
for the built-in Common Lisp types, we can't identify all the subclass
relationships among these classes, which in fact are implementation-dependent.
One could say that there are standardized subclass relationships, which
are different from the implementation-dependent subtype relationships,
but I think that approach would be confusing and cause problems. I think
it's better for the subclass relationships to reflect reality, even when
that makes them implementation-dependent. My intuition is that this will
not introduce any new portability problems that were not already present.
Alternatively, these built-in types could be allowed as specifiers in
methods, but not be considered classes. After all, they already do not
participate in the full class protocol. Built-in types are not acceptable
to MAKE-INSTANCE and are not acceptable as superclasses in DEFCLASS.
That way, there wouldn't be any issue of possible inconsistency between
SUBTYPEP and sub-class relationships. On the other hand, this could just
be ducking the issue, since one still must ask what methods are inherited
by a given object.
Perhaps what it comes down to is: what is the CLASS-OF function good for?
Any thoughts on this?
Second, while "standard-char" is well defined, I don't think it should
be a class; I imagine it would otherwise be difficult to make (class-of
#\a) return something other than (class-of #\page).
I agree with you that STANDARD-CHAR shouldn't be a class, i.e. shouldn't
be something that can have methods defined. My reason would be that it
is too specific, that is, it doesn't seem useful to have a different
method for STANDARD-CHAR than for CHARACTER for any generic function I
can think of. Thus I wouldn't allow STANDARD-CHAR until I was allowing
all of the other Common Lisp type-specifiers that are really
predications rather than classes. On the other hand, it would only take
one example of a generic function that had different methods for
STANDARD-CHAR and CHARACTER to change my mind on this one.
I don't see why there would be any special implementation problems in
CLASS-OF, though.
Third, I don't think that bit, fixnum and bignum should be defined to be
part of the required class lattice, because they correspond conceptually
to "range" types.
I agree with you here. BIT is in the same category as STANDARD-CHAR.
KEYWORD and STRING-CHAR are also in this category.
FIXNUM and BIGNUM are implementation characteristics of integers; they
don't change the behavior (given a definition of behavior abstract enough
to rule out performance differences). Thus I don't think it makes sense
for methods to make a distinction between FIXNUM and BIGNUM. This is
different from my reason for excluding BIT.
Finally, for those items that have multiple superclasses, we need to
either define an order or else remove one of the superclasses.
I agree.
I like having "list" as a class, but the precidence for NIL needs to be
defined. I'd say that NIL was a symbol first and a list second, on the
basis that "list" is an abstraction but "symbol" is quite concrete, and,
at least when I write 'em, I tend to put the concrete classes before the
abstract ones.
That was my reasoning also. Converting a partial ordering to a total
ordering for the sake of brevity, I would rank classes in order from
most specific to most general:
RATIONAL FLOAT NUMBER SYMBOL LIST VECTOR ARRAY SEQUENCE
These are all the built-in classes that definitely have subclasses.
As for simple-vector, simple-bit-vector, simple-string, my inclination
is that "simple" isn't a particularly interesting dimension to
discriminate on; removing "simple-array" would do most of the cleanup,
and saying that a "vector" is first an array and secondly a sequence
would finish it off.
I think this is similar to the fixnum/bignum situation. Simpleness of an
array is an implementation characteristic, not a behavior characteristic.
I agree with both of your points here (don't have classes for simple-xxx;
array is more specific than sequence).
On further examination, there are no requirements that stream,
hash-table, readtable, package, pathname or random-state be distinct
from other types (p 33), and my belief is that these cannot then be
required to be "first class" classes, in that (class-of (make-hash-table
...)) might return the same as (class-of (make-array ...)) for suitable
arguments.
Perhaps this can be stated in the subjunctive, e.g. "if these are
distinct types in your Common Lisp implementation, they'll probably be
distinct classes in any implementation of this spec".
The language in CLtL pp.33-5 wasn't written with the concept of
inheritance in mind, it seems. However, there are predicates defined to
test for all of these types, and they are required to be distinct from
each other (third bullet on p.35), so I don't think an implementation
could have them totally indistinguishable from other types. I.e.
(class-of (make-hash-table ...)) might return the same as (class-of
(make-array ...)) for suitable arguments, but not for -all- arguments.
Given this, it just means that (SUBTYPEP 'HASH-TABLE 'ARRAY) is
implementation-dependent, which doesn't seem fatal to the idea of
HASH-TABLE being a class. My thinking was to allow methods to
discriminate on all of the types you mentioned, except STREAM. I
exclude STREAM for the same reason as FUNCTION; its definition is too
vague (but see below).
My reasons for excluding other built-in types listed in CLtL Table 4-1:
ATOM this is (NOT CONS), and we're not doing NOT yet
[see McAllester and Zabih Boolean Classes paper
at OOPSLA for some thoughts on why NOT is hard].
COMMON specification is too vague
NIL no object can be an instance of this type
Another way of looking at these choices is that if there is a MAKE-xxx
function, or something equivalent, I have included the type, but if there
isn't, I have excluded it. Since there aren't separate functions for
making BITs, FIXNUMs, and BIGNUMs, they're excluded. FUNCTION is excluded
because there is no function to make functions, but COMPILED-FUNCTION
is included because COMPILE exists. STREAM is excluded because there
isn't one function to make streams, and in fact many different types
of objects can be streams. This line of reasoning isn't watertight,
but it's a pretty good heuristic.
∂22-Sep-86 1024 Owners-CommonLoopsCore↑.pa@Xerox.COM Class Precedence List
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 10:23:52 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 22 SEP 86 09:51:36 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 22 SEP 86 09:40:08 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 109702; Mon
22-Sep-86 12:38:18 EDT
Date: Mon, 22 Sep 86 12:37 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Class Precedence List
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860921-191928-1425@Xerox>
Message-ID: <860922123733.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 21 Sep 86 19:19 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>, Kahn.pa@Xerox.COM
A recursive rule that computes class precedence lists locally.
1) A class c1 cannot be given any super that has c1 in its
class-precedence list.
2) If c1 has one superclass c2, then the class precedence list of c1 is
(cons c1 (c-p-l c2))
3) If c1 has two superclasses, c2 and c3, then use
(cons c1 (merge-pls (c-p-l c2) (c-p-l c3))
where (merge-pls first second)
takes the prefix of first until it finds an element in common with
second.
If there is none, then use all of first. Follow by the prefix of second
up to the common element. If this has any element in common with the
rest of first, signal an error. Insert the common element. Repeat
until first is empty, then append the rest of second.
4) If there are more than 2, then merge the pairs in an associative
manner
This requires that the class-precedence-list of every class be available
explicitly. In our implementation we compute and store only the
precedence list of classes that are instantiated, or are going to be
instantiated. For example, in the world I am running right now there
are 2668 classes, of which 1736 (65%) have class-precedence-lists and
932 (35%) don't. Only 643 (24%) of the classes have actually been
instantiated, so an implementation that wasn't as concerned about
preparing things in advance of instantiation would have a higher cost
for precomputing the class-precedence-list of every class. I checked a
world that was booted this morning, rather than a fortnight ago, and
hasn't been used for program development, and the percentages are not
significantly different.
The claim is that this algorithm produces lists that obey all of Moon's
rules, is local and one pass.
"Proof"
A class with no super obeys Moon's rules
Proceed by induction.
Clearly (1) Each class precedes it own supers
(2) Local ordering is preserved, since no ordering in the individual
lists is changed by the merge. And the first element of each sublist
(the local supers) have their order preserved.
(3) Duplicate elimination always puts things as early as they can go.
Several minutes thought has shown no problem with this.???
This algorithm might be okay, but I'm having trouble understanding your
description with enough precision to be sure what it does. I can't be
sure that using the class-precedence-lists of the superclasses does the
same thing as looking directly at the constraints in each class, since
the class-precedence-list is a total ordering, and therefore contains
spurious orderings that are not implied by the partial ordering that the
programmer specified.
If you translate your algorithm to Lisp code and send it to me, I'll be
happy to check it against my algorithm, by eye and by running a thousand
test cases that I happen to have lying around. (Unfortunately I don't
have a comprehensive set of test cases that are supposed to signal errors,
but I'll try two or three).
You have the Lisp code for my algorithm, don't you? I think I sent it
to Gregor a long time ago. We are making all of the New Flavors source
code publically available, subject only to the requirement that people
who copy it don't remove our copyright, so if you don't have the code
let me know and I'll send it to you. I can send you just the class
precedence functions through the mail, or with more delay I could send
everything on some medium (maybe I have to have a signed agreement not
to yank off the copyright before I can send everything).
∂22-Sep-86 1025 Bobrow.pa@Xerox.COM Re: Class Precedence List
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 10:24:12 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 SEP 86 10:12:03 PDT
Date: 22 Sep 86 10:11 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Class Precedence List
In-reply-to: Danny Bobrow <Bobrow.pa>, Kahn's message of 21 Sep 86 19:19
PDT
To: Bobrow.pa@Xerox.COM, Kahn.pa@Xerox.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <860922-101203-1764@Xerox>
A recursive rule that computes class precedence lists locally.
1) A class c1 cannot be given any super that has c1 in its
class-precedence list.
2) If c1 has one superclass c2, then the class precedence list
of c1 is (cons c1 (c-p-l c2))
3) If c1 has two superclasses, c2 and c3, then use (cons c1
(merge-pls (c-p-l c2) (c-p-l c3))
where (merge-pls first second) takes the prefix of first until
it finds an element in common with second. If there is none, then
use all of first. Follow by the prefix of second up to the common
element. If this has any element in common with the rest of first,
signal an error. Insert the common element. Repeat until first is
empty, then append the rest of second.
4) If there are more than 2, then merge the pairs in an
associative manner
The claim is that this algorithm produces lists that obey all
of Moon's rules, is local and one pass.
Some more thought has shown that although this is true, it gives an
error in cases where Moon's multipass algorithm is claimed to work.
Consider classes with supers
class Supers Precedence Lists
F1 B C F1 B C Object
F2 A C F2 A C Object
F3 A B F3 A B Object
G F1 F2 G F1 B F2 A C Object
(The legal Moon list computed by Moon's algortihm and ours)
H G F3 Error!!! by our algorithm
But a legal Moon precedence list for H is
H G F1 F2 F3 A B C Object
Notice that the order of A and B are in opposite orders in precedence
lists for G and H. Is this freedom desirable? If not, then our
algorithm is good. If so, then ???
-- danny and ken
∂22-Sep-86 1130 Owners-CommonLoopsCore↑.pa@Xerox.COM Generic Function Objects
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 11:30:37 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 22 SEP 86 11:00:26 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 22 SEP 86 10:59:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 109808; Mon
22-Sep-86 13:58:00 EDT
Date: Mon, 22 Sep 86 13:56 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Generic Function Objects
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860921-153930-1345@Xerox>
Message-ID: <860922135659.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 21 Sep 86 15:39 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
In the existing CommonLoops papers and code, there is an object called
the discriminator and piece of code called the discriminating function.
The discriminating function was stored inside the discriminator, and
when the discriminator was "named", was also stored in the
symbol-function cell of the symbol which named the discriminator. The
discriminating-function was the thing you funcalled, the discriminator
was the thing that you passed to add-method.
A potentially better design combines the discriminator and the
discriminating function into a single, closure-like, object called the
generic function. The generic function is funcallable; funcalling it
causes method lookup to happen. Accessors which used to work on the
discriminator work directly on the generic function. In particular,
generic-function-methods returns a list of all the methods defined on a
generic function.
Generic functions are mutable, and are side-effected by add-method and
remove-method. An alternative proposal makes them immutable, add-method
and remove-method return new generic-functions, see Masinter's message
of 21-Sep-86 12:26:49 PDT.
We spent a fair amount of time discussing the implementation
implications of this. We believe that this does not cause serious
implementation problems. At least the mutable case can even be
implemented fairly efficiently in PCL.
This new scheme has not yet been discussed on this list though. This
message is intended to spark that discussion.
Well, Dick brought this up on 29 August, and I discussed it on 3 Sep
(see Message-ID: <860903155437.5.MOON@EUPHRATES.SCRC.Symbolics.COM>),
and Dick replied with some vague answers ("I think we have a cleaner design than
what you suggest."), (see Message-ID: <860903-150632-1329@Xerox>),
but it seems to have been dropped after that.
I still believe what I said back then:
The primary reason for keeping them separate is to gain the freedom
to perform implementation-dependent optimizations of the time-critical
operation of calling a generic function. In our implementation we could
rather easily make the function definition of the name of a generic
function be an acceptable argument to the other operations on generic
functions, as a synonym for the generic function meta-object itself,
but I'm not sure if all implementations could do this, since Common Lisp
defines very little of the characteristics of a compiled-function as an
object.
∂22-Sep-86 1132 Gregor.pa@Xerox.COM Re: Class Precedence List
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 11:31:51 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 SEP 86 11:31:13 PDT
Date: 22 Sep 86 11:19 PDT
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Class Precedence List
In-reply-to: Danny Bobrow <Bobrow.pa>, Kahn's message of 21 Sep 86 19:19
PDT
To: Bobrow.pa@Xerox.COM, Kahn.pa@Xerox.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860922-113113-1887@Xerox>
One problem with this algorithm is that compute-class-precedence-list is
required to be a function of the local-supers tree. It is specifically
not allowed to just snarf the CPL of a class that it comes across, but
rather must recompute it. I have not yet figured out what the
implications are, in this particular case, of violating this rule.
Another problem with this algortihm is that it doesn't, at least from
the explanation you give, seem any easier to explain than Moon's rules.
∂22-Sep-86 1300 Gregor.pa@Xerox.COM Re: Generic Function Objects
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 13:00:16 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 SEP 86 11:33:54 PDT
Date: 22 Sep 86 11:27 PDT
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Generic Function Objects
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 22 Sep 86 13:56 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860922-113354-189@Xerox>
It is my belief (actually, I am pretty sure Danny and Dick agree), that
this reduces to the problem of fast funcall for compiled, indefinite
extent lexical closure fast. We assumed that most Common Lisps had
tackled that problem, and could re-use the same technology.
∂22-Sep-86 1410 masinter.pa@Xerox.COM Re: initial class lattice
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 14:05:20 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 SEP 86 13:48:03 PDT
Date: 22 Sep 86 13:42 PDT
From: masinter.pa@Xerox.COM
Subject: Re: initial class lattice
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 22 Sep 86 12:00 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: commonloopscore↑.PA@Xerox.COM
Message-ID: <860922-134803-1141@Xerox>
The objective is to allow class-of to be fast even in implementations
where some other predicates (e.g., compiled-function-p) are slow. Any
meta-operation needs to first get the class so that it can participate
in discrimination, and meta-operations are performance critical; e.g.,
there are a number of operations (e.g., get-slot) which are defined in
terms of the meta-class rather than the class, and which might compile
inline as a method-invocation on class-of. For that reason, the leaves
of the initial class hierarchy should be restricted to be those items
which are known to be immediately computable from the object and from
its type tags.
For newly defined classes, we can insure that class-of can be executed
quickly. However, for the built-in classes, we need to integrate over
the range of Lisp implementations so as not to invalidate what would
otherwise be a good implementation technique (read: hack). If
compiled-function is allowed to inherit from vector, then it must be
that for any vector, (class-of ...) needs to ask compiled-function-p,
which could be relatively expensive. It is much preferable to "leave it
out".... certainly it can be added in for those that keep it separate.
There were reasons before to not make requirements on the implementation
of compiled functions, and they remain.
It is unacceptable to define arbitrary subclass relationships, because
the type predicates would disagree with the class predicates. (vectorp
x) but (class-of x) isn't a subclass of vector.
The major problem with "type specifiers" which are not class in
discrimination is avoiding ambiguity and insuring portability.
- - - - - - -
Another thing CLASS-OF is good for is a more principled approach to what
type-of attempts and fails at. TYPE-OF is hopelessly underspecified,
and, as such, is not useful in portable code.
CLASS-OF, however, is reasonably well specified (once the bugs in the
initial class lattice are worked out), and then an implementation
(defun type-of (x) (class-name (class-of x)))
would be a reasonable way of "cleaning up" what is otherwise a mess.
CLASS-OF allows meta-class discrimination, e.g., (mapcar #'(lambda
(slot) (get-slot x slot) (class-slots (class-of x)))).
- - - - - - - -
We should be explicit about allowable extensions to the class lattice
(e.g., for all vectors, it is only required that class-of return a
subclass of class vector, and it is possible to add intermediate classes
as well).
∂22-Sep-86 1410 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: Class Precedence List
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 14:05:27 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 22 SEP 86 14:02:42 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 22 SEP 86 13:39:46 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 110024; Mon
22-Sep-86 16:37:51 EDT
Date: Mon, 22 Sep 86 16:36 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Class Precedence List
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860922-101203-1764@Xerox>
Message-ID: <860922163653.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 22 Sep 86 10:11 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>, Ken Kahn
....Notice that the order of A and B are in opposite orders in precedence
lists for G and H. Is this freedom desirable?
I don't see why not. It seems to me that if there is no constraint on
the ordering of those classes, you are not doing the user a favor by
complaining that H is illegal when it doesn't violate any local ordering
constraints. You're just harrassing the user.
I wrote a little program that searched the world on my machine for pairs
of flavors that don't always appear in the same order. It found 1830
pairs. I think this is some sort of evidence that this freedom is, in
fact, desirable. I looked at a few pairs and they generally seem to be
flavors whose ordering doesn't matter because they have orthogonal
behavior (i.e. no methods in common).
If not, then our
algorithm is good. If so, then ???
I think this must be an example of the problem I suspected in my
previous message where your algorithm, by using a total ordering as a
standin for a partial ordering, generates spurious ordering constraints
which then get you into trouble. What are the reasons for not using the
partial ordering instead?
∂22-Sep-86 1510 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: Generic Function Objects
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 15:10:37 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 22 SEP 86 14:06:06 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 22 SEP 86 13:56:16 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 110053; Mon
22-Sep-86 16:53:37 EDT
Date: Mon, 22 Sep 86 16:52 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Generic Function Objects
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860922-113354-189@Xerox>
Message-ID: <860922165254.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 22 Sep 86 11:27 PDT
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
It is my belief (actually, I am pretty sure Danny and Dick agree), that
this reduces to the problem of fast funcall for compiled, indefinite
extent lexical closure fast. We assumed that most Common Lisps had
tackled that problem, and could re-use the same technology.
Personally I think it's important for the wide acceptance of this standard
for it to avoid features that could cause unnecessary efficiency problems
on some implementations. No matter how fast funcalling a closure is, it's
going to be a little slower than calling something that isn't a closure.
If every microsecond counts, this could be a problem.
As I said, Symbolics has no problem with this, but I think that before
putting something into the standard that might cause problems for some
implementations we should either get wider input so we can be sure that
it won't cause problems, or we should reexamine the benefits of putting
it into the standard to make sure the benefits outweigh the costs.
No one has ever answered my question of what are the benefits, unless I
missed the answer. As far as I can tell, the sole benefit is that you
can say #'FOO instead of (GENERIC-FUNCTION-NAMED 'FOO). Perhaps there
is something else that I am missing. So far no one has ever answered
this question.
∂22-Sep-86 1511 masinter.pa@Xerox.COM Re: Syntax of DEFCLASS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 15:10:53 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 SEP 86 14:44:21 PDT
Date: 22 Sep 86 14:30 PDT
From: masinter.pa@Xerox.COM
Subject: Re: Syntax of DEFCLASS
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sun, 21 Sep 86 18:20 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
line-fold: no
cc: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860922-144421-1211@Xerox>
Many of your arguments are historical ("The real problem with defstruct is that it was designed nine years ago...") I thought I would check the historical record. I've scanned the Common Lisp mail for the last 4 years and found only the following. The lack of any proposals to change defstruct, while there've been proposals galore to do lots of violence, leads me to believe that the syntax, while not the "best", is certainly adequate. And, now that there are thousands of users of Common Lisp and at least 8 textbooks and numerous courses and etc, I think we're best off living with it. I don't think a proposal to change it will fly.
Date: 1 October 1982 04:06-EDT
From: Alan Bawden <ALAN at MIT-MC>
Subject: DEFSTRUCT options syntax
To: Common-Lisp at SU-AI
From the last meeting:
17. Can we standardize on keywords always being used as
name-value pairs? The worst current deviants are
WITH-OPEN-FILE and DEFSTRUCT options.
Yes. The Lisp Machine LISP group will make a
proposal soon for OPEN, WITH-OPEN-FILE, and
DEFSTRUCT.
While everyone agrees that OPEN and WITH-OPEN-FILE should be fixed (and they already have been fixed on the Lisp Machine), the case for DEFSTRUCT is not as clear. In my opinion the change is gratuitous since the options list in a defstruct is NOT a function call. Furthermore it is more than a non-trivial incompatible change since each option has to be re-thought in light of the fact that it can now be given only one argument rather than any number. (Note that the :CONSTRUCTOR and :INCLUDE options take advantage of this multiple-argument ability.)
I asked Moon and DLW if they agreed with me on this subject. Moon replied:
Date: Thursday, 30 September 1982 00:44-EDT
From: MOON at SCRC-TENEX
To: DLW at SCRC-TENEX
cc: Alan
Re: gratuitous change to defstruct syntax.
I've changed my mind about this since August, and am now in agreement with
Alan. Partly this was caused by thinking about what it would mean to
change DEFFLAVOR to use alternating keywords and values; it seems very
clear that it would make it much worse. Thinking about this more made me
decide that some special forms have syntax that looks something like a
function call, but many are totally unrelated to function calls and trying
to wedge them into the same mold is just confused (and confusing).
Certainly the way OPEN used to be was wrong, and fixing it was a big win.
But I think DEFSTRUCT should stay with "option" or "(option args...)"
syntax, as should DEFFLAVOR, DEFSYSTEM, DEFSITE, and who knows what else.
It probably is not a coincidence that these are all "defining" forms.
DLW is also in agreement with me on this. How about it folks, can we keep DEFSTRUCT parsing its options the way it is now?
02-Oct-82 0939 Guy.Steele at CMU-10A keyword pairs and DEFSTRUCT
Date: 2 October 1982 1240-EDT (Saturday)
From: Guy.Steele at CMU-10A
To: common-lisp at SU-AI
Subject: keyword pairs and DEFSTRUCT
I am in sympathy with leaving DEFSTRUCT as is. Indeed, there may be something odd about DEF-forms. OPEN was the biggest thorn, to my mind.
13-Oct-82 1309 STEELE at CMU-20C Ballot results
Date: 13 Oct 1982 1608-EDT
From: STEELE at CMU-20C
Subject: Ballot results
To: common-lisp at SU-AI
...
27. Shall DEFMACRO, DEFSTRUCT, and other defining forms also be allowed to take documentation strings as possible and appropriate?
(y) yes (n) no
Issue 27: *** Y *** Hedrick: Y Wholey: Y Fahlman: Y Weinreb: Y Killian: Y Zubkoff: Y Moon: Y van Roggen: Y Masinter: Y RMS: Y Dyer: Y Bawden: Y Feinberg: Y Ginder: Y Burke et al.: Y Brooks: Y Gabriel: Y DECLISP: Y Steele: Y Dill: X Scherlis: Y Pitman: Y Anderson: Y
∂22-Sep-86 1628 Owners-commonloopscore↑.PA@Xerox.COM Re: initial class lattice
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 16:28:14 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 22 SEP 86 15:32:37 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.PA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 22 SEP 86 15:31:30 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 110144; Mon
22-Sep-86 18:03:58 EDT
Date: Mon, 22 Sep 86 18:03 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: initial class lattice
To: commonloopscore↑.PA@Xerox.COM
In-Reply-To: <860922-134803-1141@Xerox>
Message-ID: <860922180312.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 22 Sep 86 13:42 PDT
From: masinter.pa@Xerox.COM
The objective is to allow class-of to be fast even in implementations
where some other predicates (e.g., compiled-function-p) are slow....
For that reason, the leaves
of the initial class hierarchy should be restricted to be those items
which are known to be immediately computable from the object and from
its type tags.
....
Another thing CLASS-OF is good for is a more principled approach to what
type-of attempts and fails at. TYPE-OF is hopelessly underspecified,
and, as such, is not useful in portable code.
CLASS-OF, however, is reasonably well specified (once the bugs in the
initial class lattice are worked out), and then an implementation
(defun type-of (x) (class-name (class-of x)))
would be a reasonable way of "cleaning up" what is otherwise a mess.
So TYPE-OF a compiled function would be VECTOR. Sorry, I can't agree
that this constitutes cleaning up the mess! This is independent of the
other issues in your message and shouldn't be allowed to cast doubt
on them.
∂22-Sep-86 1757 Owners-CommonLoopsCore↑.pa@Xerox.COM default optional arguments to a generic function
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 17:57:38 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 22 SEP 86 17:50:04 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 22 SEP 86 17:45:29 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 110252; Mon
22-Sep-86 20:37:50 EDT
Date: Mon, 22 Sep 86 20:37 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: default optional arguments to a generic function
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860921-180617-1396@Xerox>
Message-ID: <860922203704.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 21 Sep 86 18:06 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The following principles seem to be ones we have agreed to with respect
to generic functions and methods.
1) Methods should be able to take any Common Lisp lambda-list. In
particular the default defmethod must be able to look like a defun.
2) defgeneric should be optional, unless special options are used, such
as :generic-function-class.
3) The contract of the generic function should be true for all methods,
and that contract should be computable from a defmethod form.
Agreed.
This seems to lead to two competing proposals (Gregor says I am
oversimplifying)
Proposal a) The generic function specifies the full argument list, and
all methods must have congruent argument lists. This leads to the
problem of defining congruence (Moon proposed some rules, but as
Masinter pointed out, they had a problem with renaming of variables used
in default value forms). It also leads to redundancy in the methods --
making it difficult to change a default value form in a single place.
However, Gregor favors this scheme as later extendible by removing
restrictions. He would allow methods to take extra keywrod args if
&allow-other-keys appears in the defgeneric.
Proposal b) The generic function specifies only the required arguments,
and methods discriminate only on those arguments. However, methods can
have arbitrary argument list beyond the required arguments. From any
method, the generic contract can be computed. All methods must have the
same number of min-args.
I'm not sure these are the only possible proposals. However, proposal
(a) certainly sounds less kludgy as described here. Note that all of
the nonsense with default-value-form congruence is only necessary if use
of optional and keyword arguments for method selection is permitted. At
this point it seems clear to me that there is no way our "sound basis"
goal will allow us to standardize on any form of that at this time,
since anything we come up with is going to be new and untried. I favor
standardizing on a minimal design that does not preclude adding more
features as extensions later, when we understand their implications.
My understanding of the user community's desires is that they would
rather see a smaller standard that is published sooner, rather than a
hairier standard that takes longer to start benefiting them.
This allows cases 1a) and 1b)
Case 1a. "draw-line"
draw-line takes an optional, the width of the line in
device dependent units. Because they are device dependent
units, each individual method would like to default this
argument on its own.
(defmethod draw-line ((dev printer) p1 p2
&optional (width 7)) ...)
(defmethod draw-line ((dev window) p1 p2
&optional (width 1)) ...)
Case 1b.
Within case 1, some methods may want to take an extra
argument. Also see case 3 which is similar.
(defmethod draw-line ((d gray-display) p1 p2
&optional (width 3)
(gray *gray1*))
..)
Date: Wed, 17 Sep 86 16:15 EDT
From: David A. Moon
The problem here is that the generic function doesn't have a
consistent contract. The meaning, or even the existence, of one
argument depends on the class of another argument. I don't see how
a caller of draw-line could operate without knowing the exact
method that was going to be called. From experience I know it's
possible to have all sorts of arguments about whether this is good
or bad programming practice. In New Flavors, these arguments were
resolved in favor of consistency of contracts, rather than the
increased flexibility of different contracts for different methods,
but not everyone was happy.
I think it is possible to know that a method is coming from a particular
part of the class lattice (without knowing the exact method) and hence
know the local contract. Consistency of generic contract is only in the
required argument set.
As I said, it's possible to have all kinds of arguments about this, and
everyone has their own idea of what they would like to see. I don't
even disagree with what you just said. However, the way we are going
around and around on this doesn't sound to me like something that is
ready for standardization. We should tread carefully in this area.
To take care of GFD#2, I propose that we allow the generic to specify
optionals that it fills in. The contract between the generic and the
methods is to always supply these required method arguments. I claim it
should not be part of the contract between the generic and the method to
provide that information.
I can't figure out what the last two sentences, taken as a whole, are saying.
I propose a lambda list keyword option
&generic-optional in the generic function. Optional argument
specifications after this provide only argument names and default value
forms, but cannot have a supplied-p variable.
For example:
(defgeneric draw (thing &generic-optional (place *draw-window*))
"Draw thing on place.")
(defmethod draw ((thing line) (place raster-display)) ...)
(defmethod draw ((thing line) (place vector-display)) ...)
Methods must have required arguments where generic-optionals are
provided. Optionals in methods cannot be discriminated on.
This is fine as a proposal, but I don't think it belongs in a standard.
Next week, or next month, there might be a different idea that seems
better.
Case 3 "move" is outlawed by this proposal, because the number of
required arguments differ.
OK.
∂22-Sep-86 1814 masinter.pa@Xerox.COM Re: default optional arguments to a generic function
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 18:14:00 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 SEP 86 18:04:16 PDT
Date: 22 Sep 86 17:58 PDT
From: masinter.pa@Xerox.COM
Subject: Re: default optional arguments to a generic function
To: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <860922-180416-1453@Xerox>
I think the causes of differences here are twofold: first, whether the
default argument behavior of a function is part of its "external"
contract or something internal, and secondarily, whether language
constructs should be added to enforce contracts.
I do not believe that the argument limits (minimum, maximum, optional,
keyword) are part of the "external contract" of a function. That is,
from the point of view of the caller, there is no difference between a
&rest argument that explicitly checks if too many arguments are supplied
and a &optional argument. While there have been a number of proposals to
add such information to Common Lisp, they have foundered partly on the
objections that such information is not part of the external interface.
If argument behavior is not part of the "external" contract, then of
course methods can simply *differ* on the number of arguments supplied.
Of course, if you get to a method with too many or too few arguments,
you will get an error, just like if you call a function with the wrong
number of arguments.
While this might be "bad programming style" in some cases, it is
legitimate in others (Kahn's arguments about local vs global
consistency).
Environment tools can help detect inconsistent use of arguments in a
method, just as they can help detect a disparity between the number of
arguments supplied and the number expected in static code.
Finally, I object to language constructs in Lisp whose primary function
is to enforce contracts between the caller and callee. While adding the
notion of functional interfaces to Lisp is an interesting research
topic, and matching the interface specification to the various
implementations of that interface a useful construct in modular
programming languages, it does not belong attached to the "object
oriented" part of the language.
Perhaps we want a construct:
(define-function-interface name argument-shape values-shape
documentation)
which asserts that "name" will take arguments described by
argument-shape (which includes both extentional and intentional type
descriptions) and returns values described by values-shape, and has the
following documentation string, and then build some environment tools
that allow programs to be compiled in such a manner that any
disagreement between the function-interface and a defintion or use is
signalled by the compiler/checker. This would be an interesting
facility. It sort of looks like DEFGENERIC. But it doesn't belong here.
Larry
∂22-Sep-86 2229 MASINTER.pa@Xerox.COM class-of compiled objects
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 22:29:04 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 SEP 86 22:27:08 PDT
From: MASINTER.pa@Xerox.COM
Date: 22 Sep 86 22:26:48 PDT
Subject: class-of compiled objects
To: (moon)
cc: commonloopscore↑.pa@Xerox.COM
Message-ID: <860922-222708-1576@Xerox>
In those implementations where compiled-function is a subtype of vector,
the only alternative would be to allow (class-name (class-of (make-array
...))) to return 'compiled-function for some unspecified arguments to
make-array, even if the results were not intended to be treated as a
compiled function.
∂22-Sep-86 2236 MASINTER.pa@Xerox.COM generic function objects
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 86 22:35:55 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 SEP 86 22:35:07 PDT
From: MASINTER.pa@Xerox.COM
Date: 22 Sep 86 22:34:47 PDT
Subject: generic function objects
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <860922-223507-1578@Xerox>
(For reference, the question is, is installing a generic function done
with
(setf (symbol-function 'foo) (make-generic-function ...))
or with
(setf (symbol-generic-function 'foo) ...)
I've been meditating on "class-named" and came up with "find-class"
instead, in keeping with "find-package". Another alternative would be
"symbol-class" but that is pretty hopeless, and the class isn't a
property of the symbol, the symbol is just a name for the class.
∂23-Sep-86 0859 Owners-commonloopscore↑.pa@Xerox.COM class-of compiled objects
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Sep 86 08:47:15 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 23 SEP 86 08:45:12 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.pa@XEROX.ARPA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 23 SEP 86 08:44:46 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 110609; Tue
23-Sep-86 11:41:09 EDT
Date: Tue, 23 Sep 86 11:41 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: class-of compiled objects
To: commonloopscore↑.pa@Xerox.COM
In-Reply-To: <860922-222708-1576@Xerox>
Message-ID: <860923114122.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 22 Sep 86 22:26:48 PDT
From: MASINTER.pa@Xerox.COM
In those implementations where compiled-function is a subtype of vector,
the only alternative would be to allow (class-name (class-of (make-array
...))) to return 'compiled-function for some unspecified arguments to
make-array, even if the results were not intended to be treated as a
compiled function.
Sure, but why is that a problem? Surely that object is indistinguishable
from a compiled-function in every other way, unless an intelligent algorithm
checked the machine instructions in it for plausibility as output from the
compiler, so why not make the class structure consistent with the rest of
the implementation in calling it a compiled-function?
∂23-Sep-86 0902 Owners-CommonLoopsCore↑.PA@Xerox.COM Name of RUN-SUPER
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Sep 86 09:02:06 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 23 SEP 86 08:58:55 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA@XEROX.ARPA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 23 SEP 86 08:58:39 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 110635; Tue
23-Sep-86 11:53:08 EDT
Date: Tue, 23 Sep 86 11:53 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Name of RUN-SUPER
To: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <860923115320.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
[This was sent last Saturday but apparently did not go through.
In resending it I changed the suggestion from NEXT-METHOD to
CALL-NEXT-METHOD.]
There is a problem with the name of RUN-SUPER. With the introduction
of multimethods, it can no longer be said that RUN-SUPER runs the method
of the superclass. It might use the next argument to choose a method,
and in fact get that method from a class much more specific than the class
from which the current method came. Similarly, the introduction of around
methods mean that RUN-SUPER could be running a more specific method, if
the next method is a primary method rather than another around method.
In both cases, RUN-SUPER is running the next method, not necessarily a
method from a superior class.
For these reasons, I feel that a more appropriate name for this
primitive would be CALL-NEXT-METHOD.
∂23-Sep-86 1354 Owners-commonloopscore↑.PA@Xerox.COM Re: initial class lattice
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Sep 86 13:54:05 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 23 SEP 86 13:50:39 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.PA@XEROX.ARPA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 23 SEP 86 13:50:24 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 111046; Tue
23-Sep-86 16:48:02 EDT
Date: Tue, 23 Sep 86 16:48 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: initial class lattice
To: commonloopscore↑.PA@Xerox.COM
In-Reply-To: <860922-134803-1141@Xerox>
Message-ID: <860923164810.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 22 Sep 86 13:42 PDT
From: masinter.pa@Xerox.COM
The objective is to allow class-of to be fast even in implementations
where some other predicates (e.g., compiled-function-p) are slow. Any
meta-operation needs to first get the class so that it can participate
in discrimination, and meta-operations are performance critical; e.g.,
there are a number of operations (e.g., get-slot) which are defined in
terms of the meta-class rather than the class, and which might compile
inline as a method-invocation on class-of. For that reason, the leaves
of the initial class hierarchy should be restricted to be those items
which are known to be immediately computable from the object and from
its type tags.
It might pay to examine this a little more closely. To continue with
the example of a compiled-function that is also a vector, the time to do
get-slot of a vector doesn't matter, as long as it doesn't slow down the
time to do get-slot of other types of objects. After all, vectors don't
have slots. Are there examples of other operations that are performance
critical for primitive objects and depend on class-of? I can't imagine
any. So the question is really whether the implementor is smart enough
to implement class-of in such a way that the exception cases, where a
complicated test is required to determine the class, don't slow down the
normal case. This seems a low enough level of issue that it shouldn't
be allowed to dictate the semantics of the language.
∂24-Sep-86 2021 Owners-commonloopscore↑.PA@Xerox.COM Re: (change-class x y) => (setf (class-of x) y)?
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 86 20:20:12 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 24 SEP 86 20:17:09 PDT
Return-Path: <DLW@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: commonloopscore↑.PA@XEROX.ARPA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 24 SEP 86 20:16:44 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 112892; Wed
24-Sep-86 23:09:39 EDT
Date: Wed, 24 Sep 86 23:14 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Re: (change-class x y) => (setf (class-of x) y)?
To: Kahn.pa@Xerox.COM
cc: commonloopscore↑.PA@Xerox.COM
In-Reply-To: <860921-171550-1381@Xerox>
Message-ID: <860924231419.9.DLW@CHICOPEE.SCRC.Symbolics.COM>
Line-fold: No
Date: 21 Sep 86 17:15 PDT
From: Ken Kahn <Kahn.pa@Xerox.COM>
I like Larry's suggestion for the same reasons that most people like
SETF -- fewer names to deal with.
Minimizing the number of names does not mean that things are necessarily
clearer, simpler, and/or easier to understand.
SETF is a construct that deals with a concept that we usually call a
"generalized variable". A generalized variable is, conceptually, a
place to put something. Evaluating the generalized variable returns the
contents of the place. Using SETF on the generalized variable stores
something into the place. That's what SETF is basically about, and
that's how you'd explain SETF in a Lisp course.
Within this conceptual framework, (CLASS-OF ...) does not constitute
a "generalized variable".
In this case, you are attempting to minimize the number of names by
overloading one name with two different functions. This does not make
things simpler or easier to learn.
P.S. Consider that it would never make sense to do (PUSH X (CLASS-OF Y)).
P.P.S. Consider that we do not grow a vector by doing (SETF (LENGTH X) 10).
∂24-Sep-86 2037 Owners-commonloopscore↑.PA@Xerox.COM Re: (change-class x y) => (setf (class-of x) y)?
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 86 20:37:04 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 24 SEP 86 20:33:49 PDT
Redistributed: commonloopscore↑.PA@XEROX.ARPA
Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 86 20:33:34 PDT
From: masinter.PA@Xerox.COM
Date: 24 Sep 86 20:33:16 PDT
Subject: Re: (change-class x y) => (setf (class-of x) y)?
In-reply-to: DLW@ALDERAAN.SCRC.Symbolics.COM's message of Wed, 24 Sep 86
23:14 EDT, <860924231419.9.DLW@CHICOPEE.SCRC.Symbolics.COM>
To: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
cc: Kahn.pa@Xerox.COM, commonloopscore↑.PA@Xerox.COM
Message-ID: <860924-203349-3799@Xerox>
All other things being equal, fewer odd names are better. Are you
claiming you like "(change-class x y)" better than "(setf (class-of x)
y)"? If not, do you have a better proposal?
P.S. Consider that it never makes sense to do (PUSH X (SYMBOL-FUNCTION
Y)) either.
P.P.S. Consider that we do shrink adjustable arrays by DECFing their
FILL-POINTER.
∂25-Sep-86 0809 Bobrow.pa@Xerox.COM Re: Class Precedence List
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 25 Sep 86 08:08:53 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 25 SEP 86 08:00:01 PDT
Date: 25 Sep 86 07:59 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Class Precedence List
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 22 Sep 86 16:36 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <860925-080001-4023@Xerox>
The search I would be interested in is not the one where there are
differences of order only, but ones in which a subclass has the classes
in a different order than a super. This could lead to strangeness for a
user who tests an operation on a superclass, and finds then happening
differently in a subclass.
However, the partial order is probably the best we can do. I have not
yet seen your code. Haven't asked Gregor.
-- danny
∂25-Sep-86 0810 Bobrow.pa@Xerox.COM [Guy Steele <gls@Think.COM>: Syntax of defstruct versus
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 25 Sep 86 08:09:05 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 25 SEP 86 08:02:33 PDT
Date: 25 Sep 86 08:02 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: [Guy Steele <gls@Think.COM>: Syntax of defstruct versus
DEFCLASS]
To: CommonLoopsCore↑.pa@Xerox.COM
cc: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <860925-080233-4027@Xerox>
I asked Guy his opinion about this issue.
Here is his response.
From: Guy Steele <gls@Think.COM>
Subject: Syntax of defstruct versus DEFCLASS
To: Bobrow.pa
Cc: gls@AQUINAS.ARPA
In-Reply-To: <860921-160133-1351@Xerox>
Message-Id: <860922161225.1.GLS@DESCARTES.THINK.COM>
Danny,
I haven't seen all of the discussion that led up to this,
of course. Moon's technical criticism of DEFSTRUCT syntax
is well taken for the most part. It has also bothered me
that the option syntax is not like other uses of keywords
in the language (namely keyword-value pairs), and that you
cannot have slot-options without specifying a value.
If DEFCLASS is to solve some of the modularity problems
such as the distinction between implementation access and
client access, then it is sufficiently different that it is
appropriate to make a clean break and design a good syntax.
If the aim is to be a semantically minimal extension of
DEFSTRUCT, then it should also be a syntactically minimal
extension of DEFSTRUCT. (How is that for waffling? I have
no strong absolute feelings about the issue; I can only
express an opinion on how it should be done relative to a
set of goals.)
As for :conc-name, I think that is really stupid. Why not
let there simply be a default way of making names, and the
default can be overridden for each slot with a slot-option?
--Guy
∂25-Sep-86 1229 masinter.pa@Xerox.COM Re: (change-class x y) => (setf (class-of x) y)?
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 25 Sep 86 12:29:28 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 25 SEP 86 11:29:36 PDT
Date: 25 Sep 86 11:21 PDT
From: masinter.pa@Xerox.COM
Subject: Re: (change-class x y) => (setf (class-of x) y)?
In-reply-to: masinter.PA's message of 24-Sep-86 20:33:16 PDT
To: commonloopscore↑.PA@Xerox.COM
Message-ID: <860925-112936-4275@Xerox>
Let me give a less "off-the-cuff" reply:
For those objects whose class is mutable, the "class-of" the object is
as much of a "generalized variable" as many of the other Common Lisp
constructs which are changed using SETF. The general direction has been
to use SETF whenver possible as the principle way in which objects are
modified; few excepts were made in Common Lisp even where tradition
would have chosen different names.
The notion that some objects have a mutable class may seem strange, but
it seems no more or less strange if the operation is called
"set-class-of" or "change-class" or "setf (class-of".
In any case, the name "change-class" is awkward; there is no other
modify-operation in Common Lisp that is called "change", although
"set-class" or "set-class-of" might be reasonable.
∂25-Sep-86 1229 masinter.pa@Xerox.COM Re: initial class lattice
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 25 Sep 86 12:29:36 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 25 SEP 86 12:20:31 PDT
Date: 25 Sep 86 12:12 PDT
From: masinter.pa@Xerox.COM
Subject: Re: initial class lattice
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 23 Sep 86 16:48 EDT
To: commonloopscore↑.PA@Xerox.COM
Message-ID: <860925-122031-4341@Xerox>
Masinter: The objective is to allow class-of to be fast even in
implementations...
Moon:
It might pay to examine this a little more closely. To continue with
the example of a compiled-function that is also a vector, the time to do
get-slot of a vector doesn't matter, as long as it doesn't slow down the
time to do get-slot of other types of objects. After all, vectors don't
have slots. Are there examples of other operations that are performance
critical for primitive objects and depend on class-of? I can't imagine
any. So the question is really whether the implementor is smart enough
to implement class-of in such a way that the exception cases, where a
complicated test is required to determine the class, don't slow down the
normal case. This seems a low enough level of issue that it shouldn't
be allowed to dictate the semantics of the language.
Masinter:
Your point is well taken. I agree now that the performance issue is not
critical.
However, the issue remains: which types in CLtL are intrinsic and which
are extrinsic? Clearly (satisfies evenp) is an extrinsic type -- it
depends on a view of the data rather than on the data itself. The
current type system is muddy enough that it allows some implementations
to treat compiled-function-p and hash-table-p and read-table-p as if
they were testing extrinsic properties rather than intrinsic ones, and
thus, the types would not correspond directly to classes.
I think this is one of those awful, picky issues that are irrelevant to
the whole proposal but that standards are made of. The tradeoff is
between power (they're classes, which means you can write discriminators
on them) and portability (some implementations might treat
compiled-function as a sublcass of vector, and others not) and the
constraint of not changing drastically the implementation requirements
of the system. Which would you rather give up?
∂25-Sep-86 1358 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: Class Precedence List
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 25 Sep 86 13:57:54 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 25 SEP 86 12:53:27 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa@XEROX.ARPA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 25 SEP 86 12:52:57 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 114016; Thu
25-Sep-86 14:58:46 EDT
Date: Thu, 25 Sep 86 14:58 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Class Precedence List
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860925-080001-4023@Xerox>
Message-ID: <860925145850.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 25 Sep 86 07:59 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The search I would be interested in is not the one where there are
differences of order only, but ones in which a subclass has the classes
in a different order than a super. This could lead to strangeness for a
user who tests an operation on a superclass, and finds then happening
differently in a subclass.
That is exactly what the New Flavors ordering rules, as compared with either
breadth-first or depth-first search, are intended to avoid. It might be that
there are cases where they don't avoid this problem, but I'd have to see
a specific example. The proposed extension, which I kind of like but have
neither implemented nor evaluated its effect on real programs, deals more
stringently with this issue by examining all pairs of component classes whose
order is unconstrained and determining whether exchanging them would alter
any inherited methods; if not, their order doesn't matter, because it doesn't
affect behavior. If so, signal an error. This extension would ensure that
no matter which of the possible total orderings consistent with the partial
ordering is chosen, the behavior is the same.
Even though I like this idea (due to KMP originally I believe) I can't
support putting it into a standard, since it hasn't been tried in the
real world.
∂26-Sep-86 0954 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: Class Precedence List
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Sep 86 09:54:11 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 26 SEP 86 09:50:47 PDT
Redistributed: CommonLoopsCore↑.pa
Received: from Cabernet.ms by ArpaGateway.ms ; 26 SEP 86 09:50:28 PDT
Date: 26 Sep 86 09:45 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Class Precedence List
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 25 Sep 86 14:58 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: CommonLoopsCore↑.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <860926-095047-5234@Xerox>
The search I would be interested in is not the one
where there are differences of order only, but ones in which a
subclass has the classes in a different order than a super.
This could lead to strangeness for a user who tests an
operation on a superclass, and finds then happening differently
in a subclass.
That is exactly what the New Flavors ordering rules, as
compared with either breadth-first or depth-first search, are
intended to avoid. It might be that there are cases where they
don't avoid this problem, but I'd have to see a specific example.
What are the class precedence list for the following
classes (flavors)
class Supers
F1 B C
F2 A C
F3 A B
F4 B A
G F1 F2
H G F3
K G F4
In particular, what are the lists for G, H and K.
H and K must have A nd B in opposite orders. Both have G as a super.
G doesn't care but must have some order.
-- danny
∂26-Sep-86 1330 Owners-CommonLoopsCore↑.pa@Xerox.COM Re: Class Precedence List
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Sep 86 13:26:41 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 26 SEP 86 12:39:22 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa@XEROX.ARPA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 26 SEP 86 12:38:48 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 115970; Fri
26-Sep-86 15:27:09 EDT
Date: Fri, 26 Sep 86 15:27 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Class Precedence List
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <860926-095028-5231@Xerox>
Message-ID: <860926152702.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 26 Sep 86 09:45 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The search I would be interested in is not the one
where there are differences of order only, but ones in which a
subclass has the classes in a different order than a super.
This could lead to strangeness for a user who tests an
operation on a superclass, and finds then happening differently
in a subclass.
That is exactly what the New Flavors ordering rules, as
compared with either breadth-first or depth-first search, are
intended to avoid. It might be that there are cases where they
don't avoid this problem, but I'd have to see a specific example.
What are the class precedence list for the following
classes (flavors)
class Supers Components
F1 B C (F1 B C)
F2 A C (F2 A C)
F3 A B (F3 A B)
F4 B A (F4 B A)
G F1 F2 (G F1 B F2 A C)
H G F3 (H G F1 F2 F3 A B C)
K G F4 (K G F1 F2 F4 B A C)
In particular, what are the lists for G, H and K.
I filled them into your message above, using a program of course.
I see; now I see what you meant by testing an operation on a
superclass and happening differently on a subclass. G is the
superclass and H is the subclass.
H and K must have A and B in opposite orders. Both have G as a super.
G doesn't care but must have some order.
That's right. If the relative ordering of A and B matters, it
should have been declared explicitly, possibly using the
:component-order option (remember, that's one of the defflavor
options whose usefulness you couldn't see). In fact in the very
many real cases where this happens that I enumerated the other
day, the relative ordering of A and B does not matter. In this
particular specific example, the programmer who wrote F3 and F4
seems to have declared explicitly that the relative ordering of
A and B is immaterial.
The proposed extension from (I think) KMP that I mentioned the
other day is intended to provide automatic detection of whether
or not the relative ordering of A and B matters, instead of
making it the responsibility of the programmer to say whether
it matters. My comments on that extension from the other day
still stand.
∂26-Sep-86 1635 Gregor.pa@Xerox.COM missing excl-low file
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Sep 86 16:34:57 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 26 SEP 86 13:43:17 PDT
Date: Fri, 26 Sep 86 13:36 PDT
From: Gregor.pa@Xerox.COM
Subject: missing excl-low file
To: CommonLoops.PA@Xerox.COM
Message-ID: <860926133653.2.GREGOR@AVALON.XEROX-PARC>
Line-fold: no
For some reason, the file excl-low.l was missing from the /pub/pcl
directory on parcvax.xerox.com. That file now exists on that directory
so people who want to use PCL in Franz Common Lisp (ExCL) should have no
problems.
Gregor
-------
∂29-Sep-86 1328 Owners-commonloops.pa@Xerox.COM getting connected
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 86 13:28:19 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 29 SEP 86 11:25:38 PDT
Return-Path: <DALY@IBM.COM>
Received: from IBM.COM ([192.5.58.7]) by Xerox.COM ; 29 SEP 86 11:15:57
PDT
Date: 29 September 1986, 13:08:34 EDT
From: "Timothy P. Daly" <DALY@ibm.com>
To: commonloops.pa@Xerox.COM
Message-Id: <092986.130835.daly@ibm.com>
Subject: getting connected
Please add my name to the list of people receiving the common loops
discussions:
DALY@IBM.COM
Thanks.
∂29-Sep-86 1816 Hostrop.PA@Xerox.COM {eris}<Lispcore>...
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 86 18:16:30 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 29 SEP 86 18:02:04 PDT
Date: 29 Sep 86 17:58:55 PDT (Monday)
From: Hostrop.PA@Xerox.COM
Subject: {eris}<Lispcore>...
To: Lispcore↑.pa@Xerox.COM, CommonLoopsCore↑.pa@Xerox.COM,
AISTest↑.x@Xerox.COM
cc: , Hostrop.PA@Xerox.COM
Reply-To: Hostrop.PA@Xerox.COM
Message-ID: <860929-180204-1109@Xerox>
...has but 3664 pgs left - Those of you writing to this directory are
encouraged to pare out obsolete versions wherever it makes sense. Your
cooperation is greatly appreciated by all patrons of {eris}<Lispcore>.
∂30-Sep-86 1701 Owners-CommonLoops.PA@Xerox.COM Anybody know how objects are represented in PCL?
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Sep 86 17:00:59 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 30 SEP 86 16:53:49 PDT
Return-Path: <luis@ingres.Berkeley.EDU>
Received: from ingres.Berkeley.EDU ([128.32.156.105]) by Xerox.COM ; 30
SEP 86 16:48:55 PDT
Received: by ingres.Berkeley.EDU (5.53/1.14)
id AA00872; Tue, 30 Sep 86 16:23:54 PDT
Date: Tue, 30 Sep 86 16:23:54 PDT
From: luis@ingres.Berkeley.EDU (Luis Miguel)
Message-Id: <8609302323.AA00872@ingres.Berkeley.EDU>
To: CommonLoops.PA@Xerox.COM
Subject: Anybody know how objects are represented in PCL?
Is there an "object table" of some kind? (like the class
hash table).
What we want to do is to be able to "swap" objects in and out
of the system as they are needed (to an object database), and need to
know what the appropriate conversions need to be.
Luis Miguel
luis@ingres.Berkeley.EDU
∂06-Oct-86 1525 Bobrow.pa@Xerox.COM Taking the politics out of Standardization
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Oct 86 15:25:05 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 06 OCT 86 14:44:52 PDT
Date: 6 Oct 86 14:44 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Taking the politics out of Standardization
To: CommonLoopsCore↑.pa@Xerox.COM
cc: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861006-144452-4065@Xerox>
As we agreed on Friday, we will create a single document:
" DRAFT
A Proposed Specification
of a Common Lisp Object Standard"
by (in alphabetical order)
D. Bobrow, L. DeMichiel, D. Gabriel, K. Kahn, S. Keene, G. Kiczales, L.
Masinter, D. Moon, D. Weinreb
from (perhaps with footnote connections)
Lucid, Symbolics, Xerox
The document will be stored on SAIL (sail.stanford.edu)
on the area
CLS,LST
password: MIXIN
It will consist of merged and rewritten parts of both documents modified
to reflect our most recent technical decisions.
The specification document will contain no history or explicit statement
of goals, but will provide a detailed technical description of the
current state of our understanding of the specification. We hope to
have a version of this document available for the next ANSI X3J13
meeting, currently scheduled for December. This implies having the
document ready for distribution to committee members in mid to late
November.
We would also like to have (at some time) a separate document describing
the rationale(s) for various decisions, and alternatives considered.
∂06-Oct-86 1658 Owners-CommonLoopsCore↑.pa@Xerox.COM Taking the politics out of Standardization
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Oct 86 16:58:07 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 06 OCT 86 16:54:20 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 06 OCT 86 16:52:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 126666; Mon
6-Oct-86 19:48:49 EDT
Date: Mon, 6 Oct 86 19:48 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Taking the politics out of Standardization
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <861006-144452-4065@Xerox>
Message-ID: <861006194832.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 6 Oct 86 14:44 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The document will be stored on SAIL (sail.stanford.edu)
on the area
CLS,LST
password: MIXIN
I think the actual directory is CLS,LSP (not LST).
Symbolics people: SU-AI:name.type[CLS,LSP]. name is six characters,
type is three. When it asks you to log in type CLS,LSP including
the comma. We don't parse SU-AI pathnames, so you need to type
the .type every time you type a pathname or it will disappear. The
directory disappears, too, but that's okay because you are logged in
to it.
∂06-Oct-86 2038 Owners-CommonLoops.PA@Xerox.COM Change of Address
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Oct 86 20:37:57 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 06 OCT 86 18:38:06 PDT
Return-Path: <Swenson.Multics@MIT-MULTICS.ARPA>
Received: from MIT-MULTICS.ARPA by Xerox.COM ; 06 OCT 86 18:32:11 PDT
Acknowledge-To: "Eric J. Swenson" <Swenson@MIT-MULTICS.ARPA>
Date: Mon, 6 Oct 86 21:27 EDT
From: "Eric J. Swenson" <Swenson@MIT-MULTICS.ARPA>
Subject: Change of Address
To: CommonLoops.PA@Xerox.COM
Message-ID: <861007012741.131505@MIT-MULTICS.ARPA>
Would you please change my address from Swenson@multics.mit.edu to
ejs%acorn@live-oak.mit.edu? Thank you. (Sorry I sent this to this
address but mail to CommonLoops-Request failed.
∂06-Oct-86 2144 Owners-CommonLoopsCore↑.PA@Xerox.COM Method Combinations
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Oct 86 21:44:02 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 06 OCT 86 21:27:00 PDT
Return-Path:
<@MC.LCS.MIT.EDU:DUSSUD%Jenner%ti-csl.csnet@CSNET-RELAY.ARPA>
Redistributed: CommonLoopsCore↑.PA
Received: from MC.LCS.MIT.EDU by Xerox.COM ; 06 OCT 86 21:25:38 PDT
Received: from CSNET-RELAY.ARPA by MC.LCS.MIT.EDU 7 Oct 86 00:13:28 EDT
Received: from ti-csl by csnet-relay.csnet id ac01434; 6 Oct 86 18:51
EDT
Received: from Jenner (jenner.ARPA) by tilde id AA01820; Mon, 6 Oct 86
16:26:53 cdt
To:
Common-Lisp-Classes-discussion%mc.lcs.mit.edu%csnet-relay.arpa@RELAY.CS.NET
Cc:
Subject: Method Combinations
Date: 6 Oct 86 16:24:33
From: DUSSUD%Jenner%ti-csl.CSNet@CSNet-Relay.ARPA
Message-Id: <DUSSUD.2738006671@Jenner>
Dave,
I noticed that the method combination declaration (:method-combination)
is an option for DEFGENERIC and not for DEFCLASS.
What's the rationale?
Thanks,
Patrick.
∂07-Oct-86 0245 Owners-CommonLoops.PA@Xerox.COM missing excl-low file
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 7 Oct 86 02:44:57 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 07 OCT 86 01:29:52 PDT
Return-Path: <sob%soma.UUCP@rice.edu>
Received: from dione.rice.edu ([128.42.1.1]) by Xerox.COM ; 07 OCT 86
01:26:10 PDT
Received: by dione.rice.edu (AA00874); Tue, 7 Oct 86 03:23:31 CDT
Received: by soma.BCM.TMC.EDU (4.13/sob/Gateway/09-22-86)
id AA01452; Tue, 7 Oct 86 03:13:24 CDT
Received: by seismo.CSS.GOV (5.54/1.14)
id AA07283; Fri, 26 Sep 86 19:44:05 EDT
Received: by beno.CSS.GOV (5.54/5.17)
id AA17460; Fri, 26 Sep 86 19:16:00 EDT
Received: from Semillon.ms by ArpaGateway.ms ; 26 SEP 86 13:43:17 PDT
Date: Fri, 26 Sep 86 13:36 PDT
From: Xerox.COM!Gregor.pa%soma.UUCP@rice.edu
Subject: missing excl-low file
To: CommonLoops.PA@Xerox.COM
Message-Id: <860926133653.2.GREGOR@AVALON.XEROX-PARC>
Line-Fold: no
For some reason, the file excl-low.l was missing from the /pub/pcl
directory on parcvax.xerox.com. That file now exists on that directory
so people who want to use PCL in Franz Common Lisp (ExCL) should have no
problems.
Gregor
-------
∂07-Oct-86 0245 Owners-CommonLoops.PA@Xerox.COM Anybody know how objects are represented in PCL?
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 7 Oct 86 02:45:06 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 07 OCT 86 01:37:47 PDT
Return-Path: <sob%soma.UUCP@rice.edu>
Received: from dione.rice.edu ([128.42.1.1]) by Xerox.COM ; 07 OCT 86
01:36:21 PDT
Received: by dione.rice.edu (AA00973); Tue, 7 Oct 86 03:28:18 CDT
Received: by soma.BCM.TMC.EDU (4.13/sob/Gateway/09-22-86)
id AA01558; Tue, 7 Oct 86 03:14:47 CDT
Received: by beno.CSS.GOV (5.54/5.17)
id AA00830; Tue, 30 Sep 86 22:11:07 EDT
Received: from Semillon.ms by ArpaGateway.ms ; 30 SEP 86 16:53:49 PDT
Return-Path: <luis@ingres.Berkeley.EDU>
Received: from ingres.Berkeley.EDU ([128.32.156.105]) by Xerox.COM ; 30
SEP 86 16:48:55 PDT
Received: by ingres.Berkeley.EDU (5.53/1.14)
id AA00872; Tue, 30 Sep 86 16:23:54 PDT
Date: Tue, 30 Sep 86 16:23:54 PDT
From: ingres.Berkeley.EDU!luis%soma.UUCP@rice.edu (Luis Miguel)
Message-Id: <8609302323.AA00872@ingres.Berkeley.EDU>
To: CommonLoops.PA@Xerox.COM
Subject: Anybody know how objects are represented in PCL?
Is there an "object table" of some kind? (like the class
hash table).
What we want to do is to be able to "swap" objects in and out
of the system as they are needed (to an object database), and need to
know what the appropriate conversions need to be.
Luis Miguel
luis@ingres.Berkeley.EDU
∂07-Oct-86 0244 Owners-commonloops.pa@Xerox.COM getting connected
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 7 Oct 86 02:44:46 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 07 OCT 86 01:27:56 PDT
Return-Path: <sob%soma.UUCP@rice.edu>
Received: from dione.rice.edu ([128.42.1.1]) by Xerox.COM ; 07 OCT 86
01:25:47 PDT
Received: by dione.rice.edu (AA00885); Tue, 7 Oct 86 03:23:53 CDT
Received: by soma.BCM.TMC.EDU (4.13/sob/Gateway/09-22-86)
id AA01488; Tue, 7 Oct 86 03:13:50 CDT
Received: by seismo.CSS.GOV (5.54/1.14)
id AA06834; Mon, 29 Sep 86 16:10:30 EDT
Received: by beno.CSS.GOV (5.54/5.17)
id AA10940; Mon, 29 Sep 86 16:10:10 EDT
Received: from Salvador.ms by ArpaGateway.ms ; 29 SEP 86 11:25:38 PDT
Return-Path: <DALY@IBM.COM>
Received: from IBM.COM ([192.5.58.7]) by Xerox.COM ; 29 SEP 86 11:15:57
PDT
Date: 29 September 1986, 13:08:34 EDT
From: "Timothy P. Daly" <ibm.com!DALY%soma.UUCP@rice.edu>
To: commonloops.pa@Xerox.COM
Message-Id: <092986.130835.daly@ibm.com>
Subject: getting connected
Please add my name to the list of people receiving the common loops
discussions:
DALY@IBM.COM
Thanks.
∂07-Oct-86 1626 Gregor.pa@Xerox.COM Re: Anybody know how objects are represented in PCL?
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 7 Oct 86 16:26:10 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 07 OCT 86 13:38:37 PDT
Date: 7 Oct 86 13:32 PDT
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Anybody know how objects are represented in PCL?
In-reply-to: ingres.Berkeley.EDU!luis%soma.UUCP@rice.edu (Luis Miguel)'s
message of Tue, 30 Sep 86 16:23:54 PDT
To: ingres.Berkeley.EDU!luis%soma.UUCP@rice.edu
cc: CommonLoops.PA@Xerox.COM
Message-ID: <861007-133837-5205@Xerox>
Date: Tue, 30 Sep 86 16:23:54 PDT
From: ingres.Berkeley.EDU!luis%soma.UUCP@rice.edu (Luis Miguel)
Is there an "object table" of some kind? (like the class
hash table).
I am not sure what you mean by object table, but if you mean: "is there
a table which has each object which was ever created in it?". The
answer is no.
What we want to do is to be able to "swap" objects in and out
of the system as they are needed (to an object database), and need
to
know what the appropriate conversions need to be.
I am also not sure what you are asking here. I get the impression that
you are trying to build some sort of permanent objects system, and that
you need to be able to dump and restore objects. What I don't know is
why you need to know the internal representation of the instances to do
this. If you want to look at the internal representation, you can look
in the file called low, but you should keep in mind that this
representation changes from release to release and that it is likely to
change across ports of PCL as well.
∂07-Oct-86 1920 Owners-CommonLoopsCore↑.PA@Xerox.COM Computing the class precedence list
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 7 Oct 86 19:20:46 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 07 OCT 86 18:38:42 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.PA@XEROX.ARPA
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 07 OCT 86 18:37:48 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 128089; Tue
7-Oct-86 21:35:55 EDT
Date: Tue, 7 Oct 86 21:35 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Computing the class precedence list
To: CommonLoopsCore↑.PA@Xerox.COM
Message-ID: <861007213525.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
As promised on Friday, this message contains the algorithm used to
compute the precedence list in New Flavors, stripped down to make it
easier to read by removing irrelevant features and arguments, and
adjusted so that it should run in any Common Lisp implementation. I
tried the one case given at the end, which returns the right answer, but
I haven't exhaustively tested for possible errors in transcription from
the algorithm we actually use. I seriously doubt that there are any
transcription errors, though.
Summary of the functions contained:
DEFCLASS1 -- fake version of DEFCLASS for testing purposes
MAP-COMPONENTS-DEPTH-FIRST -- iteration driving function (also
used by other parts of our system). The full reasons for
having this might not be obvious in the stripped down version.
MAKE-PRECEDENCE-ALIST -- convert local constraints to the
partial order, expressed as an alist
COMPOSE-FLAVOR-COMPONENTS -- convert partial order to total order
EXPLAIN-COMPONENT-ORDERING-ERROR -- auxiliary function, not included
here, that contains a lot of hair for explaining precise
details of conflicting constraints
(DEFMACRO DEFCLASS1 (NAME SUPERCLASSES)
`(SETF (GET ',NAME 'CLASS-COMPONENTS) ',(REVERSE (CONS NAME SUPERCLASSES))))
;;; Iteration driver
;;; This calls FUNCTION for each component of FLAVOR-NAME at least once. The arguments
;;; to FUNCTION are the name of the component flavor, the depth of recursion, a list
;;; of the names of all flavors that must locally precede this one (-not- a transitive
;;; closure of the precedence relations!).
;;; If FUNCTION returns NIL, iteration terminates without looking at components to right.
;;; If FUNCTION returns DONT-RECURSE, do younger brothers but not sons.
;;; Undefined components do not cause an error unless FUNCTION does not like them.
;;; The values returned by MAP-COMPONENTS-DEPTH-FIRST are meaningless to the outside caller.
(DEFUN MAP-COMPONENTS-DEPTH-FIRST (FUNCTION FLAVOR-NAME
&OPTIONAL (DEPTH 0) (PRECEDENCE NIL) (TRAIL NIL))
(LET ((CONTINUE (FUNCALL FUNCTION FLAVOR-NAME DEPTH PRECEDENCE))
(COMPONENTS (GET FLAVOR-NAME 'CLASS-COMPONENTS)))
(UNLESS (OR (MEMBER CONTINUE '(NIL DONT-RECURSE))
(MEMBER FLAVOR-NAME TRAIL)) ;Break infinite recursion
(LET ((TRAIL (CONS FLAVOR-NAME TRAIL)))
;; Use recursion to iterate backwards through list
(BLOCK RECURSE
(LABELS ((ITERATE (COMPONENTS)
(WHEN COMPONENTS
(LET ((COMPONENT (CAR COMPONENTS)))
(UNLESS (EQ COMPONENT FLAVOR-NAME)
(ITERATE (CDR COMPONENTS))
(UNLESS (MAP-COMPONENTS-DEPTH-FIRST FUNCTION
COMPONENT
(1+ DEPTH)
(CDR COMPONENTS)
TRAIL)
(RETURN-FROM RECURSE)))))))
(ITERATE COMPONENTS)))))
CONTINUE))
;;; Make alist from component flavor to the components that must be to its left
;;; due to local constraints. This is -not- the transitive closure of
;;; FLAVOR-LOCAL-COMPONENT-PRECEDENCE, but only the union of it; it's necessary
;;; not to compute the transitive closure here in order for the error reporting
;;; to be able to find cyclic constraints.
(DEFUN MAKE-PRECEDENCE-ALIST (FLAVOR-NAME)
(LET ((ALIST NIL))
(MAP-COMPONENTS-DEPTH-FIRST #'(LAMBDA (FLAVOR-NAME DEPTH PRECEDENCE)
(DECLARE (IGNORE DEPTH))
;; Construct the union of everything preceding this flavor
(LET ((ELEM (ASSOC FLAVOR-NAME ALIST)))
(IF ELEM
(SETF (CDR ELEM) (UNION (CDR ELEM) PRECEDENCE))
(PUSH (CONS FLAVOR-NAME PRECEDENCE) ALIST)))
T)
FLAVOR-NAME)
(NREVERSE ALIST)))
;;; Compute the FLAVOR-ALL-COMPONENTS list, in the appropriate order.
;;; Check for and explain circular dependencies.
;;; Missing required-flavors and undefined component flavors are detected elsewhere.
(DEFUN COMPOSE-FLAVOR-COMPONENTS (FLAVOR-NAME)
;; First combine all the local ordering constraints.
(LET ((ALIST (MAKE-PRECEDENCE-ALIST FLAVOR-NAME))
(COMPONENTS NIL) CHANGED SLOW)
;; Start with a null components list; the given flavor will always be the first
;; component, because it will be the first one encountered by MAP-COMPONENTS-DEPTH-FIRST.
;; If there are circular constraints such that the given flavor has to have something
;; to its left, this will be detected, because no other flavor is unconstrained.
;; Using the local ordering constraints, build an ordered list of components by
;; repeated depth-first tree walk until all components have been incorporated that can be.
;; The tree walk is done in such an order as to minimize the number of iterations
;; through this loop required to come up with the answer.
;; SLOW = NIL is an optimization to cut off probably unreachable branches of the tree.
(SETQ SLOW NIL)
(LOOP
(SETQ CHANGED NIL SLOW NIL)
(MAP-COMPONENTS-DEPTH-FIRST
#'(LAMBDA (FLAVOR-NAME DEPTH PRECEDENCE)
(DECLARE (IGNORE DEPTH PRECEDENCE))
(COND ((MEMBER FLAVOR-NAME COMPONENTS) T) ;Already a component, continue
((NOT (ASSOC FLAVOR-NAME ALIST)) 'DONT-RECURSE) ;Not really a component
((EVERY #'(LAMBDA (PREDECESSOR) (MEMBER PREDECESSOR COMPONENTS))
(CDR (ASSOC FLAVOR-NAME ALIST)))
;; This one can go in now, put it in and return T.
(PUSH FLAVOR-NAME COMPONENTS)
(SETQ CHANGED T))
;; If above LOOP fails, return NIL since everything to right will fail too.
;; But in SLOW mode, disable that optimization.
(T SLOW)))
FLAVOR-NAME)
(WHEN (NOT CHANGED)
;; We seem to be done; make sure all components really got incorporated.
(WHEN (= (LENGTH COMPONENTS) (LENGTH ALIST))
(RETURN))
;; Some components didn't get incorporated. Either there is an ordering
;; conflict, or the speedup didn't work. The speedup fails after recovery
;; from a conflict, because the constraints are no longer transitive. It
;; also fails in the face of partial ordering among the components of a flavor.
(IF SLOW
;; Already slow: there must be an ordering conflict.
;; Explain it nicely and recover by making an arbitrary choice.
(SETQ COMPONENTS (NRECONC (EXPLAIN-COMPONENT-ORDERING-ERROR FLAVOR-NAME ALIST
COMPONENTS)
COMPONENTS))
;; Try again without the speedup.
(SETQ SLOW T))))
;; Put list of components into normal order
(NREVERSE COMPONENTS)))
;;;; Example
(DEFCLASS1 C1 ())
(DEFCLASS1 C2 ())
(DEFCLASS1 C3 ())
(DEFCLASS1 C4 (C1 C2))
(DEFCLASS1 C5 (C3 C2))
(DEFCLASS1 C6 (C4 C5))
(COMPOSE-FLAVOR-COMPONENTS 'C6)
∂08-Oct-86 1514 Bobrow.pa@Xerox.COM Re: Method Combinations
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Oct 86 15:14:04 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 08 OCT 86 14:54:02 PDT
Date: 8 Oct 86 14:53 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Method Combinations
In-reply-to: DUSSUD%Jenner@ti-csl.CSNET's message of 6 Oct 86 16:24:33
To: DUSSUD%Jenner%ti-csl.CSNet@CSNet-Relay.ARPA
cc: CommonLoopsCore↑.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861008-145402-6443@Xerox>
I noticed that the method combination declaration
(:method-combination) is an option for DEFGENERIC and not for
DEFCLASS.
What's the rationale?
method-combination is a property of the generic function. It must be
uniform for all methods for a particular selector. It is independent of
the class of any arguments used for method specification.
-- danny
∂08-Oct-86 1559 Bobrow.pa@Xerox.COM Summary of Object Standard Discussions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Oct 86 15:59:01 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 08 OCT 86 15:51:25 PDT
Date: 8 Oct 86 15:50 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Summary of Object Standard Discussions
In-reply-to: Bobrow.pa's message of 8 Oct 86 13:50 PDT
To: CommonLoopsCore↑.pa@Xerox.COM
From: Bobrow.pa@Xerox.COM, Gregor.pa@Xerox.COM
Message-ID: <861008-155125-6521@Xerox>
This is an impression of the basic structure of the agreements we
reached (and didn't) at the design review meetings in Oregon and Palo
Alto. Please provide corrections. The full details should appear in
the documents on Sail of course (and will be hashed out some more).
DEFSTRUCT and DEFCLASS
We agreed that DEFSTRUCT in CommonLisp was overloaded. It should be
replaced in Common Lisp by a DEFCLASS and DEFRECORD (name not agreed
on).
DEFCLASS defines classes of objects. DEFRECORD defines
ways of using named accessors to fetch elements of lists, vectors, and
blocks of memory, and specialized ways of creating such items.
We agreed to recommend that DEFSTRUCT be eliminated from Common
Lisp and replaced with DEFCLASS and DEFRECORD (most implementations
would continue to provide DEFSTRUCT for backwards compatibility).
---
DEFCLASS SYNTAX
(defclass <class-name> ({<super-name>}*)
({<slot-spec>}*)
{(<option-name> {<option-argument>}*)}*)
<slot-spec> = <slot-name> |
(<slot-name> <init-value-form>
{<slot-option> <option-value>}*)
SLOT OPTIONS
slot-options include
:accessor <generic-fn-name>
:reader <generic-fn-name>
any number of readers and/or accessors can be specified
Readers define no setf -
This contrasts with defining an error setf
Users can roll their own with defmethod-setf
:initable <key or nil>
if NIL then not initable
Note that we we didn't resolve instance initialization protocol
so the real meaning of this option was not determined.
:allocation <one of :instance, :class, :dynamic, :none>
NOT AGREED (not discussed) Whether a slot can be specified with options
but no init-value-form
Declared :dynamic slots were discussed. It was felt this was a
declaration of a time space tradeoff, and hence might not belong.
Undeclared :dynamic slots were discussed, and it was felt that making
the Common Lisp function GET be generic might provide a useful way of
getting and setting undeclared slots. GET should also find declared
slots if they exist. No agreement was reached on this.
DEFCLASS OPTIONS
(:metaclass class-name)
(:documentation doc-string)
(:accessors-with-prefix symbol-or-string)
(:readers-with-prefix symbol-or-string)
:accessors-with-prefix and :readers-with-prefix are independent of
slot-option specification. Any number of any of these can be provided
-- a slot can
be given multiple accessors using this option.
Note that accessors are not generated by default. One of the accessor
generating options (:accessors-with-prefix, :readers-with-prefix,
:accessor, :reader) must be specified for accessors to be generated.
(:constructor ...)
Like the constructor option in defstruct. Precise behavior still to be
spec'd as part of specing initialization protocol
NOT AGREED
(:default-init-plist {<key> <value>}*)
This is tied up with the initialization protocol.
REJECTED
:initable-slots, (can be done using :initable slot-option only)
:init-keywords (a declaration - not appropriate)
----
MAKE-INSTANCE
(make-instance <class> &rest keys-and-values)
(initialize <instance> &rest)
As mentioned above, we didn't specify the instance intialization
protcol.
A detailed proposal for when the default value forms are run, when the
:initable slots are done and what gets passed to initialize needs to be
sent
out.
---
SLOT-VALUE
We agreed to change the name of get-slot to slot-value.
----
DEFMETHOD
SYNTAX for DEFMETHOD is
(defmethod <generic-function-name> {name-qualifier}*
<specialized-lambda-list> <decl-and-or-doc> form*)
(defmethod-setf <generic-function-name> {name-qualifier}*
<specialized-lambda-list> <specialized-setf-vars> ...)
name-qualifier is a non-null atom (or non-null symbol - NOT AGREED) used
in method-combination. It is expected that most forms will have 0 or 1
of these name-qualifiers.
CLASSICAL SYNTAX
There will be no "classical method" syntax specified in the standard.
SPECIALIZED LAMBDA LIST
A specialized-lambda-list is a Common Lisp lambda-list where any
REQUIRED argument may be replaced by (arg-name arg-specializer).
An arg-specializer is intended to specify the type of the argument.
The generic function ensures that the method is only called if the
argument is of that type, or some subtype.
An arg-specializer is either a symbol or an expression 'datum. The
symbol is interpreted as a class name. We agreed to consider later
the extensions of arg-qualifiers to the entire CL type system (along
lines proposed by Moon in an earlier message).
INDIVIDUAL METHODS
The form 'datum means that the argument must be bound to datum
for the method to be applicable. (This is the syntax for "individual
methods") We recommend that the Common Lisp type system to be extended
to allow 'X to mean the same as (SATISFIES (MEMBER arg '(X)).
Individual type specifers are more specific than any other matching
type specifier for a datum.
METHOD ARGUMENT LIST CONGRUENCE
All methods of a generic function must have congruent argument lists.
Congruency is our word to imply that the system can tell whether a call
is syntactically correct. The rules are:
1) Have the same number of required and optional arguments
2) Allow exactly the same keywords, or use &allow-other-keys
appropriately.
3) All have an &rest or not.
---
GENERIC FUNCTION Objects
There should be one object that is both funcallable and carries the
state that describes the generic function (e.g. the list of all the
method objects for this gf). This object is side-effected by
generic-functions to add and remove methods, and its data and/or code
will change to reflect any operations.
---
DEFGENERIC
AGREED:
- DEFGENERIC is NOT required before a method is defined on the
generic function.
NOT AGREED:
- The name DEFGENERIC.
DEFGENERIC is intended to provide information about the contract of the
generic function, and can be evaluated any number of times. It does not
affect existing methods on the generic function. To make FOO undefined,
one evals
(SETF (SYMBOL-FUNCTION 'FOO) NIL).
If a DEFGENERIC specifies a contract that is not congruent with the
current contract, it signals an error.
A DEFMETHOD will create a generic function if one does not exist,
thus doing a DEFGENERIC with defaults.
Syntax:
(defgeneric <gen-fn-name> <gen-fn-lambda-list> {<gf-option>}*)
(defgeneric-setf <gen-fn-name> <gen-fn-lambda-list>
<setf-lambda-list> {<gf-option>}*)
The <gen-fn-lambda-list> is like an ordinary Common Lisp lambda-list
EXCEPT that
1) optionals may not have default-forms or supplied-p
and hence the symbol does not mean a default value
of NIL. Note that optionals in the methods can have
default forms and supplied-p's.
2) key-args may not have default-forms or supplied-p
3) No aux variables
Note that the defgeneric passes to the methods exactly the arguments
it receives. Thus the lambda list in the defgeneric is primarily for
specifying the "shape" of the generic function arguments with which
all the methods must be congruent.
&GENERIC-OPTIONAL
We discussed whether to allow this new keyword in the generic function
argument list. It must appear before any other &key-words. Arguemnts
appearing after it are required arguments for the methods.
&GENERIC-OPTIONAL allow specification of default-value forms to be
provided by the generic function before discriminating on the arguments.
No agreement was reached on this issue.
GF-OPTIONS
(:documentation doc-string>)|string
(:argument-precedence-order <param-name>+)
This is a permutation of the required args of gf-lambda-list.
(:generic-function-class class-name)
(:method-class class-name)
METHOD COMBINATION SPECIFICATION
We agreed that the method combination would be specified as a specific
option in the defgeneric, but the precise syntax of that option was not
decided.
We discussed the general issue of the interaction of features specified
by options and the specification of the generic-function-class. One
possibility is to make :generic-function-class argument be
(:generic-function-class class-name+) and interpret this as mixins with
GENERIC-FUNCTION class. Specifically, method combination might be
specified as a mixin to the generic function class.
---
DYNAMIC CLASSES
Some support was evinced for a feature that would allow creation of
"dynamic classes", that is classes specified only by their supers.
Using
'(FOO FIE) instead of a class-name would get or create a class defined
exactly by the mixins FOO and FIE.
No agreement was reached on this.
---
WITH-SLOTS
We will have only one WITH-SLOTS form.
(with-slots ({car-name}|(var-name (keyword arg)*)) form*)
keywords are
:class class-name
:prefix string-or-symbol
:use-slot-value flag
Is it an error to have conflict of names?
Doing a SETF on var-name is not deemed to effect the meanings of the
slots.
We agreed to use SETF not SETQ in the specification to promote the style
of using setf.
---
INTERNAL MECHANISM OF WITH-SLOTS
We agreed to provide an interface to the code walker used by with-slots
so that people can define their own with-type macros (for encapsulation
or whatever). A proposal for this needs to be sent out.
---
SETF on qualified variables.
We discussed whether the variables which were the specialized arguments
to the method should be considered as the "same bindings" which caused
the method lookup to call this method or a rebinding.
Less esoterically, the questions are:
Is is legal to setf the specialized arguments to a method.
If so, does this affect call-next-method.
AGREED:
It is legal to setf the specialized arguments of a method.
This does not affect call-next-method.
---
DEFINE-METHOD-COMBINATION
We agreed to continue working to simplify and learn how best to explain
declarative method combination.
Moon presented a simplification of define-method-combination which also
allows the implementation of call-next-method. He will send that to the
entire list.
AGREED: The default type of method combination will allow primary,
call-next-method and :before and :after methods.
NOT AGREED whether :around methods are in the default, and whether they
are provided for all method-combination types.
"commonloopscore↑.pa"@xerox/su
Summary of Object Standard Discussions
About DEFGENERIC.
I certainly did not agree that a defgeneric was not required before any
DEFMETHODs. What I agreed to, and what I carefully restated every time
someone tried to tranform my statement into an agreement statement, was
that the first step in convincing me to not require a defining statement
for a generic function to appear before any DEFMETHODs is to rename
DEFGENERIC to something else. That is, if we are not going to require such
a defining statement, we should not have an operator with a name that says
``I, sir, am the very defining statement you might think you have to make,
but actually do not.''
Moon said this in his message:
``If you make the generic function FOO f-unbound and then do a DEFMETHOD
or DEFGENERIC for FOO, you get a new generic-function object that
doesn't know about any of the methods for the old FOO. Those methods
are gone ... so the data structure would be inconsistent.... There
could be other inconsistencies too.''
If generic functions are first-class, and if we've decided that this
first-class object (which comprises the generic function along with the
methods on it) is stored in the function cell, then FMAKUNBOUNDing it
is what you do when your intention is to `get a new generic-function
object that doesn't know about any of the <old> methods.''
I think this means that Moon did not understand what we agreed to. A
first-class generic function is the thing that you funcall to get the
generic behavior and that has the methods logically inside it. When you
drop the last pointer to the generic function object, the garbage
collector can grab it away. When you do n DEFMETHODs on FOO, the function
cell for FOO is the only thing that logically has a pointer to the generic
function associated with the name FOO. If FMAKUNBOUND does not flush every
old method, and data structures end up inconsistent, then there is a bug
in your implementation.
-rpg-
∂08-Oct-86 1817 Owners-commonloopscore↑.pa@Xerox.COM new files on CLS,LSP on SAIL
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Oct 86 18:17:04 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 08 OCT 86 18:15:22 PDT
Return-Path: <LGD@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 08 OCT 86
18:15:03 PDT
Date: 08 Oct 86 18:14 PDT
From: Linda DeMichiel <LGD@SAIL.STANFORD.EDU>
Subject: new files on CLS,LSP on SAIL
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <861008-181522-6748@Xerox>
I have placed the following files out on CLS,LSP:
concepts.tex, concepts.dvi
functions.tex, functions.dvi
impact.tex, impact.dvi
glossary.tex, glossary.dvi
design.tex, design.dvi
template.tex
macros.tex
various .toc and .tc files
The concepts.* files contain the contents of the first half of
the spec that Danny, Gregor, Dick and I drafted.
The functions.* files contain the second half; they also include some
of the changes we agreed upon last weekend. Template.tex is
an outline for an individual function page that can be spliced into
functions.tex.
Impact.tex is an empty template for the discussion of how our
specification affects existing Common Lisp functions and how it
may influence modification of Common Lisp.
Glossary.tex is an empty template for our glossary.
Design.tex is an empty template for a discussion of the design
rationale behind the specification.
Macros.tex is the macros file used by TEX.
The concepts, functions, impact, glossary, and design files
are currently set up to generate five chapters of a document
called the "Common Lisp Object System Specification." As we
discussed, we will probably want to make separate documents
for the presentation of the design rationale and meta-object
protocol. I have set the files up the current way primarily so
that they can be easy to work with for now and easy to shuffle
into or out of other documents later on.
The .toc and .tc files are used by TEX to generate individual
tables of contents. If you are concerned about up-to-the-minute
accuracy of the table of contents pages of file foo, then you
should tex foo, copy foo.toc to foo.tc, and tex foo again;
if you don't care, just ignore these files. The .idx and .fig
files can also be ignored.
Linda
∂09-Oct-86 1505 Owners-CommonLoopsCore↑.pa@Xerox.COM Summary of Object Standard Discussions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Oct 86 15:05:22 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 09 OCT 86 14:28:05 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 09 OCT 86 14:27:42 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 130440; Thu
9-Oct-86 17:26:13 EDT
Date: Thu, 9 Oct 86 17:25 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Summary of Object Standard Discussions
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <861008-155125-6521@Xerox>
Message-ID: <861009172529.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 8 Oct 86 15:50 PDT
From: Bobrow.pa@Xerox.COM, Gregor.pa@Xerox.COM
This is an impression of the basic structure of the agreements we
reached (and didn't) at the design review meetings in Oregon and Palo
Alto. Please provide corrections.
I cross-checked this against my notes. For brevity, I've deleted portions
of your message where I had nothing to add.
DEFCLASS SYNTAX
(defclass <class-name> ({<super-name>}*)
({<slot-spec>}*)
{(<option-name> {<option-argument>}*)}*)
<slot-spec> = <slot-name> |
(<slot-name> <init-value-form>
{<slot-option> <option-value>}*)
We forgot to discuss whether the syntax for <slot-spec>
is that one or the following, which I think is cleaner:
<slot-spec> = <slot-name> |
(<slot-name> <init-value-form>) |
(<slot-name> {<slot-option> <option-value>}*)
with a :default-value <slot-option>. Any objections?
SLOT OPTIONS
...
:initable <key or nil>
if NIL then not initable
We did not discuss allowing NIL here. I don't see any reason
for it; none of the other slot options allow NIL. As with the
accessors the default should be that it's not initable unless
you say something to make it initable.
Note that we we didn't resolve instance initialization protocol
so the real meaning of this option was not determined.
True.
DEFCLASS OPTIONS
....
(:accessors-with-prefix symbol-or-string)
(:readers-with-prefix symbol-or-string)
I think you mean :accessor-prefix and :reader-prefix, don't you?
Except for the names this agrees with my notes.
REJECTED
:initable-slots, (can be done using :initable slot-option only)
It doesn't say in my notes that this is rejected, only that giving it
with a list of slot names is rejected. My notes also say that we
rejected the idea that the environment should have an editor command to
automatically put in the :initable slot-options. So I'm not sure what
we decided about this. I take it the problem is that you don't want to
build in the convention that keyword symbols (same as Common Lisp
defstruct) rather than slot names (same as Zetalisp defstruct) are used
to initialize the slots?
:init-keywords (a declaration - not appropriate)
I don't know what you mean by "a declaration", but this will fall
out of resolving instance initialization.
The initialization protocol has to be worked out carefully in the
light of the method argument list congruence rules for &key arguments.
Or vice versa.
SYNTAX for DEFMETHOD is
(defmethod <generic-function-name> {name-qualifier}*
<specialized-lambda-list> <decl-and-or-doc> form*)
(defmethod-setf <generic-function-name> {name-qualifier}*
<specialized-lambda-list> <specialized-setf-vars> ...)
I don't like the term "name-qualifier"; the word "name" here is just a
noise word. My notes just say "qualifier". Plain "qualifier", with
"method qualifier" used when method context is not obvious, would be
better than "name-qualifier".
SPECIALIZED LAMBDA LIST
A specialized-lambda-list is a Common Lisp lambda-list where any
REQUIRED argument may be replaced by (arg-name arg-specializer).
We need to be careful to be consistent with CLtL in the use of the
words "argument", "arg", and "parameter".
INDIVIDUAL METHODS
The form 'datum means that the argument must be bound to datum
for the method to be applicable. (This is the syntax for "individual
methods") We recommend that the Common Lisp type system to be extended
to allow 'X to mean the same as (SATISFIES (MEMBER arg '(X)).
I think we have to require that, not recommend it, otherwise parameter
specializers would not be a subset of type specifiers.
(SATISFIES (MEMBER arg '(X)) is not a valid CL type specifier;
you meant to say (MEMBER x).
My notes say we agreed that the funny Common Loops exception to the
normal argument-precedence-order for methods on individuals won't fly.
The method argument list congruence rules have to be stated very
precisely, especially the parts involving &key. I guess I can
take another try at that later this week if no one else has.
DEFGENERIC
To make FOO undefined, one evals
(SETF (SYMBOL-FUNCTION 'FOO) NIL).
No, you mean (FMAKUNBOUND 'FOO). I don't think we discussed this enough.
If you make the generic function FOO f-unbound and then do a DEFMETHOD
or DEFGENERIC for FOO, you get a new generic-function object that
doesn't know about any of the methods for the old FOO. Those methods
are gone (except in the PCL meta-object protocol class-direct-methods
would still know about those methods, so the data structure would be
inconsistent). There could be other inconsistencies too. In New
Flavors currently you get the same generic-function object back again,
to avoid inconsistencies similar to these. Perhaps making f-unbound a
generic function should not be a defined operation in the standard?
If a DEFGENERIC specifies a contract that is not congruent with the
current contract, it signals an error.
We didn't discuss this, if my notes are complete. I assume you mean it
only signals an error if there are methods whose parameters are not
congruent with the new defgeneric's parameters. That's okay; at this
point the program development environment comes into play, so we
shouldn't say any more.
My notes say "we need to write up clearly the about four ways thought up
so far to extend this to discriminating on optional/keyword arguments",
but don't say that any particular person took responsibility.
(:argument-precedence-order <param-name>+)
This is a permutation of the required args of gf-lambda-list.
RPG said JonL has a proposal for a better way to do this, but I don't
think any of us have seen it yet. It should be written up and sent to
the mailing list.
WITH-SLOTS
(with-slots ({car-name}|(var-name (keyword arg)*)) form*)
Change <var-name> to <instance>, an expression that evaluates to an
instance. No reason to limit the possible expressions to variables.
The expression is evaluated exactly once. According to my notes we
agreed on that.
We agreed to use SETF not SETQ in the specification to promote the style
of using setf.
My notes don't say that. They say we agreed after discussing this and
other similar topics that we weren't writing a prescriptive style manual
for Common Lisp.
I actually think it would be better to do the opposite; if SETQ works inside
of WITH-SLOTS it should be used in examples, otherwise people who half-understand
how it is implemented will think that SETQ doesn't work and only SETF can be used
to set the slot pseudovariables that WITH-SLOTS creates.
Other things in my notes:
We agreed that calling CHANGE-CLASS inside of a method or inside of a
WITH-SLOTS can cause semantic problems and also implementation problems.
Semantic problems if the methods or slots you're already working with
are no longer applicable. Implementation problems if the slots move
around in the memory layout of the instance. We left it that we need to
work over the mail on the detailed description of when CHANGE-CLASS is
and is not valid.
We will recommend but not require that compiling a file containing
defclass, defgeneric, and defmethod forms does not side-effect the
Lisp world in which the compiler is running.
We agreed that in the default type of method combination, if there
are :before, :after, or :around methods, but no primary method, that
signals an error instead of assuming a primary method that returns NIL.
According to my notes we agreed that defmethod puts in type declarations
for the specialized parameters. I don't remember agreeing on that,
but why not.
We need better terminology for:
"argument specifier" -- looks like we settled on "parameter specializer"
"standard-type-class" or "primitive class" or "builtin class"
The proliferation of -setf functions (e.g. remove-method-setf) is getting
disturbing and maybe we need an explicit notion of the generic function
objects that do setfs.
I'm working on writing up the current state of the define-method-combination
syntax discussion, but I don't know if I'll finish that today.
∂09-Oct-86 1544 Owners-commonloopscore↑.pa@Xerox.COM Summary of Object Standard Discussions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Oct 86 15:44:29 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 OCT 86 15:41:11 PDT
Return-Path: <RPG@SAIL.STANFORD.EDU>
Redistributed: commonloopscore↑.pa
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 09 OCT 86
15:40:53 PDT
Date: 09 Oct 86 15:40 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: Summary of Object Standard Discussions
To: commonloopscore↑.pa@Xerox.COM
Message-ID: <861009-154111-1088@Xerox>
About DEFGENERIC.
I certainly did not agree that a defgeneric was not required before any
DEFMETHODs. What I agreed to, and what I carefully restated every time
someone tried to tranform my statement into an agreement statement, was
that the first step in convincing me to not require a defining statement
for a generic function to appear before any DEFMETHODs is to rename
DEFGENERIC to something else. That is, if we are not going to require such
a defining statement, we should not have an operator with a name that says
``I, sir, am the very defining statement you might think you have to make,
but actually do not.''
Moon said this in his message:
``If you make the generic function FOO f-unbound and then do a DEFMETHOD
or DEFGENERIC for FOO, you get a new generic-function object that
doesn't know about any of the methods for the old FOO. Those methods
are gone ... so the data structure would be inconsistent.... There
could be other inconsistencies too.''
If generic functions are first-class, and if we've decided that this
first-class object (which comprises the generic function along with the
methods on it) is stored in the function cell, then FMAKUNBOUNDing them
is what you do when your intention is to `get a new generic-function
object that doesn't know about any of the <old> methods.''
I think this means that Moon did not understand what we agreed to. A
first-class generic function is the thing that you funcall to get the
generic behavior and that has the methods logically inside it. When you
drop the last pointer to the generic function object, the garbage
collector can grab it away. When you do n DEFMETHODs on FOO, the function
cell for FOO is the only thing that logically has a pointer to the generic
function associated with the name FOO. If FMAKUNBOUND does not flush every
old method, and data structures end up inconsistent, then there is a bug
in your implementation.
-rpg-
∂09-Oct-86 1615 Owners-commonloopscore↑.pa@Xerox.COM "Classes" Document and Agreements Summary
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Oct 86 16:14:54 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 OCT 86 16:09:05 PDT
Return-Path: <kempf%hplabsc@hplabs.HP.COM>
Redistributed: commonloopscore↑.pa
Received: from hplabs.HP.COM ([192.5.58.10]) by Xerox.COM ; 09 OCT 86
16:02:53 PDT
Received: from hplabsc by hplabs.HP.COM ; Thu, 9 Oct 86 15:56:54 pdt
Received: by hplabsc ; Thu, 9 Oct 86 15:55:24 pdt
Date: Thu, 9 Oct 86 15:55:24 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8610092255.AA05179@hplabsc>
To: common-lisp-classes-discussion@mc.lcs.mit.edu,
commonloopscore↑.pa@Xerox.COM
Subject: "Classes" Document and Agreements Summary
Cc: snyder%hplabsc@hplabs.HP.COM
I read through the "Classes" document in detail, and the executive
summary posted by Danny on Oct. 8. Below is a list of detailed
questions, comments, and corrections which I noticed. There are
several meta-comments, however, which I've summarized at the top
to remove them from the chaff. I plan to get the updated documents
off of Sail and will post any additional comments, as needed.
I hope you'll keep us posted about progress, we've got a lot of
applications people here who are interested in the result. I'll
also post comments on the MetaObject Protocol in the Xerox document
as I get a chance to read through it. I hope these comments can
be of some help. It looks like the standard is starting to shape
up.
Jim Kempf kempf@hplabs
-----------------------------------------------------------------
METACOMMENTS
*"Classes" sounds like an excellent name!
*With reference to pgs. 9 and 39 in the "Classes" document,
it would seem that there may be some cases where a user-defined
class might want to inherit from a built-in class. The canonical
example is the class STREAM which one might want to have as the
parent for the class WINDOW in an object-oriented window system.
This would also be a reason to have a class for STREAM, instead
of excluding it, as on pg. 39. Has anyone given thought to how
this would fit in with the proposed CommonWindows standard?
*Does method combination go through the generic function or
through the method itself? If the former, then couldn't method
combination be done using macros? If the latter, then obviously
not. What is the relation between method combination and
DEFGENERIC? Couldn't the :INTERFACE keyword argument to DEFGENERIC
be used to achieve the same effect with somewhat less cognitive
complexity? In general, I support an effort to make method
combination easier to use and understand. There seems to be
a good deal of power in the idea, but it needs to be better
integrated with generic functions. See also the comments below
about defining a new class of generic functions.
*The convention for including documentation strings in this
document seems to deviate from the CLtL standard. Is this
a good idea?
*The user-accessable hook to the code walker looks like a
good idea. We'll be interested in seeing the result, though
it might be more appropriate as part of the MetaObject
protocol, since its primary use would seem to be in defining
new metaclasses.
COMMENTS (page numbers reference the "Classes" document)
pg. 5-CLASS-OF/TYPE-OF relationship needs some clarification
for instance objects. What will TYPE-OF return when applied
to an instance object? See comment below on TYPEP
pg. 5-:CLASS option-Is this for class slots? If so, it seems
to be a retraction of some earlier discussion about doing
this in the metaclass. What about inheritance of class
slots? Are seperate copies of class state maintained in
the super and subclass objects or not?
pg. 7-Presumably (TYPE-OF <object>) -> <class-name> for
TYPEP to work correctly?
pg. 7-How is automatic updating of instances done when it is
redefined? Are there any hooks for user defined transformation
of instance state? For class state (re. :CLASS option above)?
Is there some way for a user to override this? Consider the
case of developing extensions to a programming environment
while using the environment. One might not want old instances
of a redefined class to be updated, if the behavior of the
redefined class was not yet solid; otherwise, the environment
might break.
pg. 9-Couldn't :DYNAMIC be done with a subobject. That is, couldn't
one have a slot into which an object with the necessary state was
inserted when required, rather than have the extra slots added
to the object (basically, an Occam's Razor argument)?
pg. 10-The defaults for these options are listed at the end of the
paper. Shouldn't they be here? In particular, for the access
functions.
pg. 12-MAKE-INSTANCE as a generic function could potentially conflict
with the lambda list congruency test, unless initialization is
done by a seperate, class specific function (ie. with the class
name as the prefix).
pg. 14-The term "setf-lambda-list" appears to be used differently in
the middle and at the end of the page. In the middle, the term means
a qualified list, at the end, not.
pg. 15-DECLARE should be :DECLARE, and "affect" should be "effect"
(nit-picky English).
pg. 15-For the :ARGUMENT-PRECEDENCE-ORDER, what happens if not
all the parameters are included?
pg. 16-How is :GENERIC-FUNCTION-CLASS different from :INTERFACE?
That is, why would anyone what to define a different generic
function class rather than simply use a different interface definition?
Same comment goes for method combination (as mentioned in the
METACOMMENTS section).
pg. 17-I presume the :CLASS option was included so that lambda
list parameters which were not qualified could be opened up using
the WITH-SLOTS special form. If so, then why allow super class names
as well? Isn't it rather more appropriate to have the name following
:CLASS designate a class or any subclass, as with the class qualifiers
in the lambda list? And what if the parameter isn't of that class
at runtime?
pg. 18-Does CALL-NEXT-METHOD do the same thing as the current
RUN-SUPER in PCL?
pg. 19-Why not have PRINT simply be a generic function? Also, why
not have EQUALP (and perhaps EQUAL, and EQL as well) be generic
functions? This would allow programmers to define their own
notions of equality for two instances, and could come in handy
when objects have circularity.
pg. 21-Need some overview about what method combination is
and some simple examples of when it would come in handy.
Also, a simple glossery of terms, as at the beginning
of the document. Such terms as "primary method" are used
without definition.
pg. 21-What is :PRETTY-NAME used for?
pg. 21-To what extend does the parameter list differ
from DEFMACRO?
pg. 23-24-Some explanation of how these examples work
would be helpful. Also, aren't keywords self evaluating?
If so, then why quote them in the examples?
pg. 24-LOOP is not (yet) standard CL. Should probably
be replaced by something that is.
pg. 26-Must a generic function be defined before
DEFINE-METHOD-COMBINATION is evaluated? Must all
the mentioned methods? Any of them?
pg. 27-What are the internal arguments mentioned in
the paragraph after the CALL-COMPONENT-METHOD syntax
description?
pg. 32-There is a typo at the top of the page. The
second instance of (PIE CINNAMON APPLE) should be
(PASTRY CINNAMON APPLE).
pg. 37-The default info. here is good, but should
be moved up to where the options are defined.
pg. 39-STREAM might want to have a class associated
with it, for reasons cited in the METACOMMENTS
section.
∂09-Oct-86 1637 RPG Summary of Object Standard Discussions
∂09-Oct-86 1505 Owners-CommonLoopsCore↑.pa@Xerox.COM Summary of Object Standard Discussions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Oct 86 15:05:22 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 09 OCT 86 14:28:05 PDT
Return-Path: <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 09 OCT 86 14:27:42 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 130440; Thu
9-Oct-86 17:26:13 EDT
Date: Thu, 9 Oct 86 17:25 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Summary of Object Standard Discussions
To: CommonLoopsCore↑.pa@Xerox.COM
In-Reply-To: <861008-155125-6521@Xerox>
Message-ID: <861009172529.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 8 Oct 86 15:50 PDT
From: Bobrow.pa@Xerox.COM, Gregor.pa@Xerox.COM
This is an impression of the basic structure of the agreements we
reached (and didn't) at the design review meetings in Oregon and Palo
Alto. Please provide corrections.
I cross-checked this against my notes. For brevity, I've deleted portions
of your message where I had nothing to add.
DEFCLASS SYNTAX
(defclass <class-name> ({<super-name>}*)
({<slot-spec>}*)
{(<option-name> {<option-argument>}*)}*)
<slot-spec> = <slot-name> |
(<slot-name> <init-value-form>
{<slot-option> <option-value>}*)
We forgot to discuss whether the syntax for <slot-spec>
is that one or the following, which I think is cleaner:
<slot-spec> = <slot-name> |
(<slot-name> <init-value-form>) |
(<slot-name> {<slot-option> <option-value>}*)
with a :default-value <slot-option>. Any objections?
SLOT OPTIONS
...
:initable <key or nil>
if NIL then not initable
We did not discuss allowing NIL here. I don't see any reason
for it; none of the other slot options allow NIL. As with the
accessors the default should be that it's not initable unless
you say something to make it initable.
Note that we we didn't resolve instance initialization protocol
so the real meaning of this option was not determined.
True.
DEFCLASS OPTIONS
....
(:accessors-with-prefix symbol-or-string)
(:readers-with-prefix symbol-or-string)
I think you mean :accessor-prefix and :reader-prefix, don't you?
Except for the names this agrees with my notes.
REJECTED
:initable-slots, (can be done using :initable slot-option only)
It doesn't say in my notes that this is rejected, only that giving it
with a list of slot names is rejected. My notes also say that we
rejected the idea that the environment should have an editor command to
automatically put in the :initable slot-options. So I'm not sure what
we decided about this. I take it the problem is that you don't want to
build in the convention that keyword symbols (same as Common Lisp
defstruct) rather than slot names (same as Zetalisp defstruct) are used
to initialize the slots?
:init-keywords (a declaration - not appropriate)
I don't know what you mean by "a declaration", but this will fall
out of resolving instance initialization.
The initialization protocol has to be worked out carefully in the
light of the method argument list congruence rules for &key arguments.
Or vice versa.
SYNTAX for DEFMETHOD is
(defmethod <generic-function-name> {name-qualifier}*
<specialized-lambda-list> <decl-and-or-doc> form*)
(defmethod-setf <generic-function-name> {name-qualifier}*
<specialized-lambda-list> <specialized-setf-vars> ...)
I don't like the term "name-qualifier"; the word "name" here is just a
noise word. My notes just say "qualifier". Plain "qualifier", with
"method qualifier" used when method context is not obvious, would be
better than "name-qualifier".
SPECIALIZED LAMBDA LIST
A specialized-lambda-list is a Common Lisp lambda-list where any
REQUIRED argument may be replaced by (arg-name arg-specializer).
We need to be careful to be consistent with CLtL in the use of the
words "argument", "arg", and "parameter".
INDIVIDUAL METHODS
The form 'datum means that the argument must be bound to datum
for the method to be applicable. (This is the syntax for "individual
methods") We recommend that the Common Lisp type system to be extended
to allow 'X to mean the same as (SATISFIES (MEMBER arg '(X)).
I think we have to require that, not recommend it, otherwise parameter
specializers would not be a subset of type specifiers.
(SATISFIES (MEMBER arg '(X)) is not a valid CL type specifier;
you meant to say (MEMBER x).
My notes say we agreed that the funny Common Loops exception to the
normal argument-precedence-order for methods on individuals won't fly.
The method argument list congruence rules have to be stated very
precisely, especially the parts involving &key. I guess I can
take another try at that later this week if no one else has.
DEFGENERIC
To make FOO undefined, one evals
(SETF (SYMBOL-FUNCTION 'FOO) NIL).
No, you mean (FMAKUNBOUND 'FOO). I don't think we discussed this enough.
If you make the generic function FOO f-unbound and then do a DEFMETHOD
or DEFGENERIC for FOO, you get a new generic-function object that
doesn't know about any of the methods for the old FOO. Those methods
are gone (except in the PCL meta-object protocol class-direct-methods
would still know about those methods, so the data structure would be
inconsistent). There could be other inconsistencies too. In New
Flavors currently you get the same generic-function object back again,
to avoid inconsistencies similar to these. Perhaps making f-unbound a
generic function should not be a defined operation in the standard?
If a DEFGENERIC specifies a contract that is not congruent with the
current contract, it signals an error.
We didn't discuss this, if my notes are complete. I assume you mean it
only signals an error if there are methods whose parameters are not
congruent with the new defgeneric's parameters. That's okay; at this
point the program development environment comes into play, so we
shouldn't say any more.
My notes say "we need to write up clearly the about four ways thought up
so far to extend this to discriminating on optional/keyword arguments",
but don't say that any particular person took responsibility.
(:argument-precedence-order <param-name>+)
This is a permutation of the required args of gf-lambda-list.
RPG said JonL has a proposal for a better way to do this, but I don't
think any of us have seen it yet. It should be written up and sent to
the mailing list.
WITH-SLOTS
(with-slots ({car-name}|(var-name (keyword arg)*)) form*)
Change <var-name> to <instance>, an expression that evaluates to an
instance. No reason to limit the possible expressions to variables.
The expression is evaluated exactly once. According to my notes we
agreed on that.
We agreed to use SETF not SETQ in the specification to promote the style
of using setf.
My notes don't say that. They say we agreed after discussing this and
other similar topics that we weren't writing a prescriptive style manual
for Common Lisp.
I actually think it would be better to do the opposite; if SETQ works inside
of WITH-SLOTS it should be used in examples, otherwise people who half-understand
how it is implemented will think that SETQ doesn't work and only SETF can be used
to set the slot pseudovariables that WITH-SLOTS creates.
Other things in my notes:
We agreed that calling CHANGE-CLASS inside of a method or inside of a
WITH-SLOTS can cause semantic problems and also implementation problems.
Semantic problems if the methods or slots you're already working with
are no longer applicable. Implementation problems if the slots move
around in the memory layout of the instance. We left it that we need to
work over the mail on the detailed description of when CHANGE-CLASS is
and is not valid.
We will recommend but not require that compiling a file containing
defclass, defgeneric, and defmethod forms does not side-effect the
Lisp world in which the compiler is running.
We agreed that in the default type of method combination, if there
are :before, :after, or :around methods, but no primary method, that
signals an error instead of assuming a primary method that returns NIL.
According to my notes we agreed that defmethod puts in type declarations
for the specialized parameters. I don't remember agreeing on that,
but why not.
We need better terminology for:
"argument specifier" -- looks like we settled on "parameter specializer"
"standard-type-class" or "primitive class" or "builtin class"
The proliferation of -setf functions (e.g. remove-method-setf) is getting
disturbing and maybe we need an explicit notion of the generic function
objects that do setfs.
I'm working on writing up the current state of the define-method-combination
syntax discussion, but I don't know if I'll finish that today.
∂09-Oct-86 1709 Bobrow.pa@Xerox.COM Re: Summary of Object Standard Discussions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Oct 86 17:08:53 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 OCT 86 17:04:35 PDT
Date: 9 Oct 86 17:04 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Summary of Object Standard Discussions
To: commonloopscore↑.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861009-170435-1178@Xerox>
(Response to RPG)
About DEFGENERIC.
I certainly did not agree that a defgeneric was not required
before any DEFMETHODs. What I agreed to, and what I carefully
restated every time someone tried to tranform my statement into an
agreement statement, was that the first step in convincing me to
not require a defining statement for a generic function to appear
before any DEFMETHODs is to rename DEFGENERIC to something else.
We certainly agreed to disagree about the name of this. How about
the name DESCRIBE-GENERIC. If all the things said about DEFGENERIC
in my note had DESCRIBE-GENERIC for DEFGENERIC, then would you agree
DESCRIBE-GENERIC was done implicily by each DEFMETHOD, and the user
could give a DESCRIBE-GENERIC to obtain a non-default generic function?
(Response to Moon)
If you make the generic function FOO f-unbound and then do a
DEFMETHOD or DEFGENERIC for FOO, you get a new generic-function
object that doesn't know about any of the methods for the old FOO.
Those methods are gone (except in the PCL meta-object protocol
class-direct-methods would still know about those methods, so the
data structure would be inconsistent).
What data structure is inconsistent. If one did
(DEFMETHOD FOO ((X c1))...)
(DEFMETHOD FOO ((X c2))...)
(SETQ ZZ (SYMBOL-FUNCTION FOO))
(SETF (SYMBOL-FUNCTION 'FOO) NIL)
or (FMAKUNBOUND 'FOO) ;; I don't understand the difference
Then ZZ is bound to a funcallable object (a generic function) that will
indeed call the first method on an instance of c1. It is also be the
case that a "name" generated for the user for the first method may be
confusing. Doing the two DEFMETHODS again will indeed create a new
generic-function object stored in the symbol function cell of FOO.
The methods will be different, and both stored in the
class-direct-methods of the class c1. This implies perhaps that we need
some protocol for destroying generic-function objects that removes
things from class-direct-methods.
My notes don't say that. They say we agreed after discussing
this and other similar topics that we weren't writing a
prescriptive style manual for Common Lisp.
My memory was that although we were not writing a prescriptive style
manual we agreed that SETQ was a bad historical holdover, and that by
example we were going to encourage the other style.
<slot-spec> = <slot-name> |
(<slot-name> <init-value-form>) | (<slot-name>
{<slot-option> <option-value>}*)
with a :default-value <slot-option>. Any objections?
I don't like those nasty four words (it is an error) about
non-initialized variables. If we want uninitialized variables, then
this syntax is fine with me.
:initable <key or nil> if NIL then not initable
We did not discuss allowing NIL here. I don't see any reason
for it; none of the other slot options allow NIL. As with the
accessors the default should be that it's not initable unless you
say something to make it initable.
How about programs generating structures. For them, a NIL might be
appropriate. But the initialization protocol should be worked out. I
prefer slot names to be used as keys rather than keywords in any event
if we have any default.
I don't like the term "name-qualifier"; the word "name" here is
just a noise word. My notes just say "qualifier". Plain
"qualifier", with "method qualifier" used when method context is
not obvious, would be better than "name-qualifier".
"qualifier" is fine -- both are better than "option"
My notes say we agreed that the funny Common Loops exception to
the normal argument-precedence-order for methods on individuals
won't fly.
Agreed.
If a DEFGENERIC specifies a contract that is not
congruent with the current contract, it signals an error.
We didn't discuss this, if my notes are complete. I assume you
mean it only signals an error if there are methods whose parameters
are not congruent with the new defgeneric's parameters. That's
okay; at this point the program development environment comes into
play, so we shouldn't say any more.
There may be other problems between DESCRIBE-GENERICs. Should users be
able to change method-combination or generic-function class? Perhaps.
WITH-SLOTS
(with-slots ({var-name}|
(var-name (keyword arg)*)) form*)
Change <var-name> to <instance>, an expression that evaluates
to an instance. No reason to limit the possible expressions to
variables. The expression is evaluated exactly once. According to
my notes we agreed on that.
I remember thinking that this was consistent, but that we had not yet
agreed to this extension. It is OK with me. Of course it makes sense
only if :class is specified explicitly, and that would have to be said.
No type inference machinery except for variable-names declared in the
method lambda-list.
According to my notes we agreed that defmethod puts in type
declarations for the specialized parameters. I don't remember
agreeing on that, but why not.
I don't know what this means?
The proliferation of -setf functions (e.g. remove-method-setf)
is getting disturbing and maybe we need an explicit notion of the
generic function objects that do setfs.
Should we go back to
(defmethod (:setf foo) ...)
since qualifiers are not around the name.
DOCUMENTATION
When are pieces of the Symbolics document appearing on SAIL? Can
someone summarize for me what agreements on writing and combining were
reached.
-- danny
∂09-Oct-86 1811 Owners-CommonLoopsCore↑.PA@Xerox.COM "Classes" Document and Agreements Summary
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Oct 86 18:11:38 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 OCT 86 18:09:39 PDT
Return-Path: <@MC.LCS.MIT.EDU:kempf%hplabsc@hplabs.HP.COM>
Redistributed: CommonLoopsCore↑.PA
Received: from MC.LCS.MIT.EDU by Xerox.COM ; 09 OCT 86 18:09:09 PDT
Received: from hplabs.HP.COM by MC.LCS.MIT.EDU 9 Oct 86 21:08:50 EDT
Received: from hplabsc by hplabs.HP.COM ; Thu, 9 Oct 86 15:56:54 pdt
Received: by hplabsc ; Thu, 9 Oct 86 15:55:24 pdt
Date: Thu, 9 Oct 86 15:55:24 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8610092255.AA05179@hplabsc>
To: common-lisp-classes-discussion@mc.lcs.mit.edu,
commonloopscore↑.pa@Xerox.COM
Subject: "Classes" Document and Agreements Summary
Cc: snyder%hplabsc@hplabs.HP.COM
I read through the "Classes" document in detail, and the executive
summary posted by Danny on Oct. 8. Below is a list of detailed
questions, comments, and corrections which I noticed. There are
several meta-comments, however, which I've summarized at the top
to remove them from the chaff. I plan to get the updated documents
off of Sail and will post any additional comments, as needed.
I hope you'll keep us posted about progress, we've got a lot of
applications people here who are interested in the result. I'll
also post comments on the MetaObject Protocol in the Xerox document
as I get a chance to read through it. I hope these comments can
be of some help. It looks like the standard is starting to shape
up.
Jim Kempf kempf@hplabs
-----------------------------------------------------------------
METACOMMENTS
*"Classes" sounds like an excellent name!
*With reference to pgs. 9 and 39 in the "Classes" document,
it would seem that there may be some cases where a user-defined
class might want to inherit from a built-in class. The canonical
example is the class STREAM which one might want to have as the
parent for the class WINDOW in an object-oriented window system.
This would also be a reason to have a class for STREAM, instead
of excluding it, as on pg. 39. Has anyone given thought to how
this would fit in with the proposed CommonWindows standard?
*Does method combination go through the generic function or
through the method itself? If the former, then couldn't method
combination be done using macros? If the latter, then obviously
not. What is the relation between method combination and
DEFGENERIC? Couldn't the :INTERFACE keyword argument to DEFGENERIC
be used to achieve the same effect with somewhat less cognitive
complexity? In general, I support an effort to make method
combination easier to use and understand. There seems to be
a good deal of power in the idea, but it needs to be better
integrated with generic functions. See also the comments below
about defining a new class of generic functions.
*The convention for including documentation strings in this
document seems to deviate from the CLtL standard. Is this
a good idea?
*The user-accessable hook to the code walker looks like a
good idea. We'll be interested in seeing the result, though
it might be more appropriate as part of the MetaObject
protocol, since its primary use would seem to be in defining
new metaclasses.
COMMENTS (page numbers reference the "Classes" document)
pg. 5-CLASS-OF/TYPE-OF relationship needs some clarification
for instance objects. What will TYPE-OF return when applied
to an instance object? See comment below on TYPEP
pg. 5-:CLASS option-Is this for class slots? If so, it seems
to be a retraction of some earlier discussion about doing
this in the metaclass. What about inheritance of class
slots? Are seperate copies of class state maintained in
the super and subclass objects or not?
pg. 7-Presumably (TYPE-OF <object>) -> <class-name> for
TYPEP to work correctly?
pg. 7-How is automatic updating of instances done when it is
redefined? Are there any hooks for user defined transformation
of instance state? For class state (re. :CLASS option above)?
Is there some way for a user to override this? Consider the
case of developing extensions to a programming environment
while using the environment. One might not want old instances
of a redefined class to be updated, if the behavior of the
redefined class was not yet solid; otherwise, the environment
might break.
pg. 9-Couldn't :DYNAMIC be done with a subobject. That is, couldn't
one have a slot into which an object with the necessary state was
inserted when required, rather than have the extra slots added
to the object (basically, an Occam's Razor argument)?
pg. 10-The defaults for these options are listed at the end of the
paper. Shouldn't they be here? In particular, for the access
functions.
pg. 12-MAKE-INSTANCE as a generic function could potentially conflict
with the lambda list congruency test, unless initialization is
done by a seperate, class specific function (ie. with the class
name as the prefix).
pg. 14-The term "setf-lambda-list" appears to be used differently in
the middle and at the end of the page. In the middle, the term means
a qualified list, at the end, not.
pg. 15-DECLARE should be :DECLARE, and "affect" should be "effect"
(nit-picky English).
pg. 15-For the :ARGUMENT-PRECEDENCE-ORDER, what happens if not
all the parameters are included?
pg. 16-How is :GENERIC-FUNCTION-CLASS different from :INTERFACE?
That is, why would anyone what to define a different generic
function class rather than simply use a different interface definition?
Same comment goes for method combination (as mentioned in the
METACOMMENTS section).
pg. 17-I presume the :CLASS option was included so that lambda
list parameters which were not qualified could be opened up using
the WITH-SLOTS special form. If so, then why allow super class names
as well? Isn't it rather more appropriate to have the name following
:CLASS designate a class or any subclass, as with the class qualifiers
in the lambda list? And what if the parameter isn't of that class
at runtime?
pg. 18-Does CALL-NEXT-METHOD do the same thing as the current
RUN-SUPER in PCL?
pg. 19-Why not have PRINT simply be a generic function? Also, why
not have EQUALP (and perhaps EQUAL, and EQL as well) be generic
functions? This would allow programmers to define their own
notions of equality for two instances, and could come in handy
when objects have circularity.
pg. 21-Need some overview about what method combination is
and some simple examples of when it would come in handy.
Also, a simple glossery of terms, as at the beginning
of the document. Such terms as "primary method" are used
without definition.
pg. 21-What is :PRETTY-NAME used for?
pg. 21-To what extend does the parameter list differ
from DEFMACRO?
pg. 23-24-Some explanation of how these examples work
would be helpful. Also, aren't keywords self evaluating?
If so, then why quote them in the examples?
pg. 24-LOOP is not (yet) standard CL. Should probably
be replaced by something that is.
pg. 26-Must a generic function be defined before
DEFINE-METHOD-COMBINATION is evaluated? Must all
the mentioned methods? Any of them?
pg. 27-What are the internal arguments mentioned in
the paragraph after the CALL-COMPONENT-METHOD syntax
description?
pg. 32-There is a typo at the top of the page. The
second instance of (PIE CINNAMON APPLE) should be
(PASTRY CINNAMON APPLE).
pg. 37-The default info. here is good, but should
be moved up to where the options are defined.
pg. 39-STREAM might want to have a class associated
with it, for reasons cited in the METACOMMENTS
section.
∂10-Oct-86 1601 Owners-CommonLoopsCore↑.pa@Xerox.COM Classes document available on SAIL
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Oct 86 16:01:26 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 10 OCT 86 15:25:59 PDT
Return-Path: <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Redistributed: CommonLoopsCore↑.pa
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by
Xerox.COM ; 10 OCT 86 15:25:27 PDT
Received: from JUNCO.SCRC.Symbolics.COM by
STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 131545; Fri
10-Oct-86 18:14:24 EDT
Date: Fri, 10 Oct 86 18:13 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Classes document available on SAIL
To: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <861010181313.1.SKEENE@JUNCO.SCRC.Symbolics.COM>
Line-fold: No
I transferred the file containing the Classes document over to
"classes.txt" on the CLS,LSP directory at SAIL. It's in a format that
should be easy for you all to read, although the page breaks are
probably wrong for printers.
I expect to get to work on Tuesday to start merging my pieces of the
Classes document into the files that Linda set up. This has been a
busy week for us here, and I haven't had a chance to get started on it
yet.
∂10-Oct-86 1601 Bobrow.pa@Xerox.COM Computing the class precedence list
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Oct 86 16:01:31 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 10 OCT 86 15:51:00 PDT
Date: 10 Oct 86 15:51 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Computing the class precedence list
To: CommonLoopsCore↑.pa@Xerox.COM
cc: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861010-155100-1243@Xerox>
Another way of explaining class precedence list.
The class precedence list is a left to right, depth first linearization
of the transitive closure of inheritance from the local super classes of
a class. It satisfies three constraints:
Constraint-0) A class appears only once in the list
Constraint-1) A class always precedes in the list all its local super
classes
Constraint-2) The order of the local supers is preserved
Stating C1 and C2 slightly differently:
C-1-2) A class must follow any class it is a direct super of,
or any class it follows in a local-supers list.
The class precedence can be constructed in three steps.
1) Walk the inheritance tree in left to right depth first order,
recording all super classes in the order visited.
2) Remove duplicates, preserving the last occurrence of any class.
(This can actually be combined with step 1 without extra consing.).
3) Traverse the resluting list from left to right. If for any class c1,
there is a class to its right that c1 should follow (by C-1-2), move c1
to the right of the rightmost such class.
If any class needs to be moved a second time, it means there is a loops
of constraints that cannot be satisfied.
∂10-Oct-86 1601 Gregor.pa@Xerox.COM yaccpla (yet another compute class precedence list algorithm)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Oct 86 16:01:39 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 10 OCT 86 15:59:10 PDT
Date: Fri, 10 Oct 86 15:58 PDT
From: Gregor.pa@Xerox.COM
Subject: yaccpla (yet another compute class precedence list algorithm)
To: CommonLoopsCore↑.pa@Xerox.COM
Message-ID: <861010155847.2.GREGOR@AVALON.XEROX-PARC>
Line-fold: no
This code implements a compute-class-precedence-list algorithm the many
and varied features of which Danny will describe in a separate message.
Using this changed defclass1 macro you can try it on all the same
examples as the other algorithm.
(DEFMACRO DEFCLASS1 (NAME SUPERCLASSES)
`(progn (SETF (GET ',NAME 'CLASS-COMPONENTS) ',(REVERSE (CONS NAME SUPERCLASSES)))
(setf (get ',name 'supers) ',superclasses)))
(defun compute-class-precedence-list (class)
(let ((cpl ())
(must-precede-alist ()))
;; We start by computing two values.
;; CPL
;; The depth-first left-to-right up to joins walk of the supers tree.
;; MUST-PRECEDE-ALIST
;; An alist of the must-precede relations. The car of each element of the
;;; must-precede-alist is a class, the cdr is all the classes which must
;; precede that class in the CPL.
;;
;; Note that the actual walk is breadth-first, right-to-left.
;;
(labels ((walk-supers (class &optional precedence)
(format t "~% ~S ~S" class precedence)
(let ((elem (assoc class must-precede-alist)))
(if elem
(setf (cdr elem) (nunion (cdr elem) precedence))
(push (cons class precedence) must-precede-alist)))
(let* ((rsupers (reverse (cons class (get class 'supers))))
(precedence (cdr rsupers)))
(do ((sup rsupers (cdr sup))
(pre precedence (cdr pre)))
((null pre))
(walk-supers (car sup) pre)))
(unless (member class cpl) (push class cpl))))
(walk-supers class)
;; For each class in the cpl, make sure that there are no classes after it which
;; should be before it. We do this by cdring down the list, making sure that for
;; each element of the list, none of its must-precedes come after it in the list.
;; We use a hand-coded loop so that we can splice things in and out of the CPL as
;; we go.
(let ((tail cpl)
(element nil)
(move nil)
(moves nil))
(loop (when (null tail) (return))
(setq element (car tail)
move nil)
(dolist (must-precede (cdr (assoc element must-precede-alist)))
;; This hairy setq does the following:
;; The outer OR means if you have already found a MOVE, don't drop it
;; unless you find another move.
;; The inner OR means once you have found a move, only look for another
;; move that comes after it.
;; The result is that we look for the farthest possible move.
(setq move (or (member must-precede (or move
(cdr tail)))
move)))
(when move
(when (member element moves)
(EXPLAIN-class-ORDERING-ERROR class MUST-PRECEDE-ALIST cpl))
(push element moves)
(setf (cdr move) (cons element (cdr move)))
(setf (car tail) (cadr tail)) ;OK to use Interlisp delete trick since it
(setf (cdr tail) (cddr tail))) ;will never be the last element of the list.
(setq tail (cdr tail)))
(copy-list cpl)))))
-------
∂13-Oct-86 1823 RPG Greetings
To: common-lisp-object-system@SAIL.STANFORD.EDU
This mailing list is the replacement for
commonloopscore↑.pa@xerox.com
You can mail to it using the address
common-lisp-object-system@sail.stanford.edu
The request address is
common-lisp-object-system-request@sail.stanford.edu
-rpg-
∂13-Oct-86 1832 Bobrow.pa@Xerox.COM Re: Summary of Object Standard Discussions (Repeat of last
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 13 Oct 86 18:31:49 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 13 OCT 86 18:30:34 PDT
Date: 13 Oct 86 18:31 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Summary of Object Standard Discussions (Repeat of last
week)
To: common-lisp-object-system@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861013-183034-1785@Xerox>
(Response to RPG)
About DEFGENERIC.
I certainly did not agree that a defgeneric was not required
before any DEFMETHODs. What I agreed to, and what I carefully
restated every time someone tried to tranform my statement into an
agreement statement, was that the first step in convincing me to
not require a defining statement for a generic function to appear
before any DEFMETHODs is to rename DEFGENERIC to something else.
We certainly agreed to disagree about the name of this. How about
the name DESCRIBE-GENERIC. If all the things said about DEFGENERIC
in my note had DESCRIBE-GENERIC for DEFGENERIC, then would you agree
DESCRIBE-GENERIC was done implicily by each DEFMETHOD, and the user
could give a DESCRIBE-GENERIC to obtain a non-default generic function?
(Response to Moon)
If you make the generic function FOO f-unbound and then do a
DEFMETHOD or DEFGENERIC for FOO, you get a new generic-function
object that doesn't know about any of the methods for the old FOO.
Those methods are gone (except in the PCL meta-object protocol
class-direct-methods would still know about those methods, so the
data structure would be inconsistent).
What data structure is inconsistent. If one did
(DEFMETHOD FOO ((X c1))...)
(DEFMETHOD FOO ((X c2))...)
(SETQ ZZ (SYMBOL-FUNCTION FOO))
(SETF (SYMBOL-FUNCTION 'FOO) NIL)
or (FMAKUNBOUND 'FOO) ;; I don't understand the difference
Then ZZ is bound to a funcallable object (a generic function) that will
indeed call the first method on an instance of c1. It is also be the
case that a "name" generated for the user for the first method may be
confusing. Doing the two DEFMETHODS again will indeed create a new
generic-function object stored in the symbol function cell of FOO.
The methods will be different, and both stored in the
class-direct-methods of the class c1. This implies perhaps that we need
some protocol for destroying generic-function objects that removes
things from class-direct-methods.
My notes don't say that. They say we agreed after discussing
this and other similar topics that we weren't writing a
prescriptive style manual for Common Lisp.
My memory was that although we were not writing a prescriptive style
manual we agreed that SETQ was a bad historical holdover, and that by
example we were going to encourage the other style.
<slot-spec> = <slot-name> |
(<slot-name> <init-value-form>) | (<slot-name>
{<slot-option> <option-value>}*)
with a :default-value <slot-option>. Any objections?
I don't like those nasty four words (it is an error) about
non-initialized variables. If we want uninitialized variables, then
this syntax is fine with me.
:initable <key or nil> if NIL then not initable
We did not discuss allowing NIL here. I don't see any reason
for it; none of the other slot options allow NIL. As with the
accessors the default should be that it's not initable unless you
say something to make it initable.
How about programs generating structures. For them, a NIL might be
appropriate. But the initialization protocol should be worked out. I
prefer slot names to be used as keys rather than keywords in any event
if we have any default.
I don't like the term "name-qualifier"; the word "name" here is
just a noise word. My notes just say "qualifier". Plain
"qualifier", with "method qualifier" used when method context is
not obvious, would be better than "name-qualifier".
"qualifier" is fine -- both are better than "option"
My notes say we agreed that the funny Common Loops exception to
the normal argument-precedence-order for methods on individuals
won't fly.
Agreed.
If a DEFGENERIC specifies a contract that is not
congruent with the current contract, it signals an error.
We didn't discuss this, if my notes are complete. I assume you
mean it only signals an error if there are methods whose parameters
are not congruent with the new defgeneric's parameters. That's
okay; at this point the program development environment comes into
play, so we shouldn't say any more.
There may be other problems between DESCRIBE-GENERICs. Should users be
able to change method-combination or generic-function class? Perhaps.
WITH-SLOTS
(with-slots ({var-name}|
(var-name (keyword arg)*)) form*)
Change <var-name> to <instance>, an expression that evaluates
to an instance. No reason to limit the possible expressions to
variables. The expression is evaluated exactly once. According to
my notes we agreed on that.
I remember thinking that this was consistent, but that we had not yet
agreed to this extension. It is OK with me. Of course it makes sense
only if :class is specified explicitly, and that would have to be said.
No type inference machinery except for variable-names declared in the
method lambda-list.
According to my notes we agreed that defmethod puts in type
declarations for the specialized parameters. I don't remember
agreeing on that, but why not.
I don't know what this means?
The proliferation of -setf functions (e.g. remove-method-setf)
is getting disturbing and maybe we need an explicit notion of the
generic function objects that do setfs.
Should we go back to
(defmethod (:setf foo) ...)
since qualifiers are not around the name.
DOCUMENTATION
When are pieces of the Symbolics document appearing on SAIL? Can
someone summarize for me what agreements on writing and combining were
reached.
-- danny
----- End Forwarded Messages -----
-- danny
∂13-Oct-86 2206 LGD new object system spec files
To: common-lisp-object-system@SAIL.STANFORD.EDU
There is a new version of functi.tex and all files derived from it on
[CLS,LSP] on SAIL. The old tex source file has been renamed to functi.1.
Linda
∂13-Oct-86 2333 Owners-CommonLoopsInternal↑.x@Xerox.COM Mailing list addition
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 13 Oct 86 23:33:18 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 13 OCT 86 23:29:27 PDT
Return-Path: <@SAIL.STANFORD.EDU:SMITCHELL@USC-ECL.ARPA>
Redistributed: CommonLoopsInternal↑.x
Received: from SAIL.STANFORD.EDU (SU-AI.ARPA) by Xerox.COM ; 13 OCT 86
23:28:22 PDT
Received: from USC-ECL.ARPA by SAIL.STANFORD.EDU with TCP; 13 Oct 86
23:09:23 PDT
Date: Mon, 13 Oct 86 23:08:58 PDT
From: "Steve Mitchell" <SMITCHELL@USC-ECL.ARPA>
Subject: Mailing list addition
To: cl-object-oriented-programming@SU-AI.ARPA
cc: ailist-request@SRI-STRIPE.ARPA, nl-kr-request@ROCHESTER.ARPA,
smitchell@USC-ECL.ARPA
Message-ID: <12246648417.53.SMITCHELL@USC-ECL.ARPA>
Please add me to your mailing list. Thanks in advance!
Steven Mitchell
smitchell@usc-ecl.arpa
-------
∂14-Oct-86 0754 skeene@STONY-BROOK.SCRC.Symbolics.COM Re: Summary of Object Standard Discussions (Repeat of last
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 14 Oct 86 07:53:39 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 132678; Tue 14-Oct-86 10:17:10 EDT
Date: Tue, 14 Oct 86 10:15 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Summary of Object Standard Discussions (Repeat of last
week)
To: Bobrow.pa@Xerox.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <861013-183034-1785@Xerox>
Message-ID: <861014101523.7.SKEENE@JUNCO.SCRC.Symbolics.COM>
Line-fold: No
Date: 13 Oct 86 18:31 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
DOCUMENTATION
When are pieces of the Symbolics document appearing on SAIL? Can
someone summarize for me what agreements on writing and combining were
reached.
-- danny
Sure. Here's a summary of what we decided will happen with the
documentation. There will be 3 documents that will go together. The
title and authors are as you noted in an earlier message. The outline
of the first document follows, and you'll see that the writing is split
up more or less evenly between Lucid (L) and Symbolics (S).
Part I: Progammer's Interface
Part II: Meta Object Protocol
We see this as a separate document. We have not yet discussed
anything specific about this document, except that it needs to be
written.
Part III: Design Rationale
This is another separate document. It will include the reasons
underlying certain design decisions.
We will all be adding to this document as we go along. To start,
I'm going to put in sections from the "Classes" document.
----------------------------------------------
Part I: Progammer's Interface
1 Introduction (brief, no history) (L)
2 Concepts
Classes (L)
-Defining classes
-Structure of class objects (slots)
-Creating instances
-Superclasses
-Inheritance
-Class precedence (brief)
-Accessing slots
-Types and Classes
Generic Functions and Methods (S)
-Compare g-f's and ordinary functions
-Defining generic functions
-Defining methods
Method Selection (S)
Method Combination (S)
Class Precedence List (S)
Meta Objects (L)
-Metaclass
-Method class
-Generic function class
3 Alphabetic List of Functions
[Each function page has the following fields: Purpose, Syntax,
Arguments, Example, Remarks, See Also]
[We are going to merge existing documentation from both the Lucid
and the Symbolics documents. Some of the documentation must be revised
according to the discussions we had.]
add-method (L)
argument-precedence-order (L)
call-next-method (S)
change-class (L)
class-of (L)
defclass (S)
defgeneric (S)
defgeneric-setf (S)
define-method-combination (S) (and related functions)
defmethod (S)
defmethod-setf (S)
function-parameters (L)
generic-function-p (L)
get-method (L)
lambda-list-argument-specifiers (L)
make-generic (L)
make-instance (L)
method-combination (L)
remove-class (L) [under discussion]
remove-method (L)
remove-setf-method (L)
slot-value (L)
with-slots (S)
4 Existing CL Functions that Need to Change
describe (S)
documentation (L)
print-object (S)
5 Glossary
∂14-Oct-86 1659 RPG Anonymous Generic Function Proposal
To: common-lisp-object-system@SAIL.STANFORD.EDU
Here are a series of proposals for making anonymous generic functions
in a pleasant way. There are three sorts of non-named-by-symbol generic
function forms we need to define: pure anonymous, LABELS equivalent, and
FLET equivalent. There is probably only one reasonable way to define
anonymous generic functions:
#'(generic-lambda <method-spec>*)
where <method-spec> is
(<qualified lambda list> . <body>)
For example:
#'(generic-lambda
(((x1 c1)(x2 c2)) (foo x1 x2))
(((x1 c3) (x2 c4)) (baz x1 x2)))
The two remaining cases are for LABELS and FLET equivalents.
GENERIC-FUNCTION-LABELS corresponds to LABELS and GENERIC-FLET corresponds
to FLET. These names are negotiable.
For each of GENERIC-FUNCTION-LABELS and GENERIC-FLET there are two
possible styles, called the modular and the distributed styles. In the
modular style:
(generic-function-labels (<generic-function-spec>*) . <body>)
where <generic-function-spec> is
(<generic-function-name> <method-spec>*)
where the <method-spec> is as above. Here is an example:
(generic-function-labels
((gf1
;;; First method on gf1
(((x1 c1) (x2 c2)) (when (recursivep x1) (gf1 (f1 x1) (f2 x2))))
;;; Second method on gf1
(((x1 c3) (x2 c3)) (when (recursivep x1) (gf2 (f3 x1) (f4 x2)))))
(gf2
;;; First method on gf2
(((x1 c4)(x2 c5)) (gf1 (f5 x1) (f6 x2)))
;;; Second method on gf2
(((x1 c6)(x2 c7)) (gf2 (f7 x1)(f8 x2)))))
;;; Now we use these guys
(gf1 x1 y1) ... (gf2 xn yn))
The distributed style looks like this:
(generic-function-labels (<named-method-spec>*) . <body>)
where <named-method-spec> is
(<generic-function-name> <method-spec>)
Here is an example:
(generic-function-labels
;;; First method on gf1
((gf1 ((x1 c1) (x2 c2)) (when (recursivep x1) (gf1 (f1 x1) (f2 x2))))
;;; Second method on gf1
(gf1 ((x1 c3) (x2 c3)) (when (recursivep x1) (gf2 (f3 x1) (f4 x2))))
;;; First method on gf2
(gf2 ((x1 c4)(x2 c5)) (gf1 (f5 x1) (f6 x2)))
;;; Second method on gf2
(gf2 ((x1 c6)(x2 c7)) (gf2 (f7 x1)(f8 x2))))
;;; Now we use these guys
(gf1 x1 y1) ... (gf2 xn yn))
The GENERIC-FLET admits both modular and distributed styles, which
I won't show.
I'm not sure which I favor. Of course, one can ADD-METHOD to any of
these generic functions.
I made an assumption when devising these, which was that it is not
possible for a method to call another method without the intervention
of a generic function. In this case, a hairier reference scheme is
needed.
-rpg-
∂14-Oct-86 1849 Gregor.pa@Xerox.COM Re: Anonymous Generic Function Proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Oct 86 18:49:04 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 OCT 86 17:29:17 PDT
Date: 14 Oct 86 17:29 PDT
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Anonymous Generic Function Proposal
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 14 Oct 86
16:59 PDT
To: RPG@SAIL.STANFORD.EDU
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861014-172917-2958@Xerox>
For some reason, your message had no "To:" field on it when it got to
me. I assume it was to this list.
These are interesting syntaxes for making anonymous generic functions.
But this doesn't address what I think is an important issue. Namely,
what does generic-function-lables really mean?
Clearly, it defines a lexical scope in which the symbol "names" a
generic function with the given method. But what does it mean if at the
time that scope is entered dynamically, the global function cell of the
symbol has a generic function in it?
1. Should the global generic function have the lexical methods added to
it within the lexical scope?
2. Or should there just be a whole new generic function within that
lexical scope? This generic function just has the methods specified in
the gf-labels form.
Clearly #2 is much easier to implement, but is it the semantics we want?
Given the names you chose (as opposed to mlet and mlabels) I would
**guess** that you implicitly favor #2.
I had always thought that we would do something like #1, but I haven't
thought about it hard enough to know if it makes sense.
∂15-Oct-86 0751 RPG Anonymous Generic Functions
To: common-lisp-object-system@SAIL.STANFORD.EDU
Having 3 minutes until I rush to the airport, let me elaborate slightly
on my proposal.
The reason for anonymous generic functions is the same reason for
anonymous functions. The user wants to define a locally known
generic function without the possibility of other methods
leaking in. The compiler can optimize it better because it can
see everything, etc, etc. It gives a complete unit with name
references entirely local to the definition.
Early on, the small minds didn't think FLET and LABELS would be useful,
but I see lots of user code, and lots of implementor code, using them
everywhere.
The generic-function-labels construct builds a generic function
which has nothing to do with any symbols. The methods are in the generic
function object. Presumably the construct logically does a MAKE-GENERIC and
some ADD-METHODS. It behaves with respect to symbol-function cells the
way that DEFUN and LABELS behave:
(defmethod foo (x)(format t "Hm, the global definition?~%"))
(generic-function-labels
((foo (x) (format t "Hah, the right thing!~%")))
(foo 7))
=> Hah, the right thing!
-rpg-
∂15-Oct-86 1312 @MC.LCS.MIT.EDU:Moon@STONY-BROOK.SCRC.Symbolics.COM "Classes" Document and Agreements Summary
Received: from MC.LCS.MIT.EDU by SAIL.STANFORD.EDU with TCP; 15 Oct 86 13:12:26 PDT
Received: from STONY-BROOK.SCRC.Symbolics.COM by MC.LCS.MIT.EDU 15 Oct 86 14:43:11 EDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 134062; Wed 15-Oct-86 14:37:11 EDT
Date: Wed, 15 Oct 86 14:35 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: "Classes" Document and Agreements Summary
To: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
cc: common-lisp-classes-discussion@mc.lcs.mit.edu,
snyder%hplabsc@hplabs.HP.COM
In-Reply-To: <8610092255.AA05179@hplabsc>
Message-ID: <861015143540.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 9 Oct 86 15:55:24 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
*With reference to pgs. 9 and 39 in the "Classes" document,
it would seem that there may be some cases where a user-defined
class might want to inherit from a built-in class. The canonical
example is the class STREAM which one might want to have as the
parent for the class WINDOW in an object-oriented window system.
This would also be a reason to have a class for STREAM, instead
of excluding it, as on pg. 39. Has anyone given thought to how
this would fit in with the proposed CommonWindows standard?
The short answer is that we are limiting this project to proposing
a standard for object-oriented programming, and we are specifically
refraining from redesigning the rest of Common Lisp. I'm sure that
once there is a standard for object-oriented programming there will
be a movement to make some changes to Common Lisp to take advantage
of that, and probably streams will be one of the areas affected.
A slightly longer answer is that the built-in data types are implemented
in different ways in different Common Lisp implementations. Thus some
implementations do streams in such a way that subclassing would be
possible, while others do them in a non-extensible way. We don't want
to limit the ability of those latter implementations to adopt the
standard. Implementations that have windows and have extensible streams
can certainly make their window class inherit from their stream class;
nothing in the proposed standard is intended to forbid that. It's just
that it isn't portable to every implementation.
∂15-Oct-86 1503 Bobrow.pa@Xerox.COM Method Combination
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Oct 86 15:02:50 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 OCT 86 14:41:04 PDT
Date: 15 Oct 86 14:39 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Method Combination
To: Common-Lisp-Object-system@sail.stanford.edu
cc: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>,gregor.pa@Xerox.COM
Message-ID: <861015-144104-3961@Xerox>
This message contains a proposal for some primitives that we claim allow
simplification of the defining form for method combination. With these
primitives, we then define some standard method combination types for
examination and comment.
1) Finding the methods with appropriate qualifiers. Use of this
primitive would replace the current 3rd argument to
define-method-combination.
Methods of a generic function have a list of qualifiers consisting of
all the items <qualifier> in the defining form:
(defmethod <generic-function> {<qualifier>}* ... )
The primary method has qualifier list (). find-methods uses a filter
argument that is a list. In matching, the qualifier list must be equal
to the filter list, except that * in the filter list matches any item in
the qualifier list.
(find-methods generic-function
&optional (filter ())
(order :most-specific-first))
Selects methods of the generic function that match
filter. Returns a list of such methods ordered
by specificity determined by order.
filter = ({<qualifier>|*}*)
order = :most-specific-first | :most-specific-last
examples:
(find-methods generic-function) ;; primary methods in usual order
(find-methods generic-function (:before))
(find-methods generic-function (:after) :most-specific-last)
2) Primitives for constructing method combination forms. These are
designed to be used in the expression that constructs the body of a
combined method.
(make-method-call method-object)
Constructs a lisp form that calls
method-function of method-object
(make-call-first-method method-list)
Constructs a call of first method on method-list
with remainder of method-list
accessible to call-next-method.
(method-from-form lisp-form)
Constructs a method from a Lisp form for a particular generic
function.
----
We can now compare the current syntax for method combination with this
new style using the primitives given:
**Current style:
(define-method-combination1 :daemon ()
((before :every :most-specific-first (:before))
(primary :every :most-specific-first ())
(after :every :most-specific-last (:after)))
`(multiple-value-prog2
(call-component-methods before)
(call-component-method (car primary) (cdr primary))
(call-component-methods after)))
----
**New style (without supporting additional macros)
(define-method-combination2 :daemon (generic-function)
`(multiple-value-prog2
(progn ,@(mapcar #'(lambda (m) (make-method-call m))
(find-methods generic-function (:before))))
,(make-call-first-method (find-methods generic-function)))
(progn ,@(mapcar #'(lambda (m) (make-method-call m))
(find-methods generic-function
(:after)
:most-specific-last)))
(define-method-combination2 :around+daemon (generic-function)
(make-call-first-method
(append
(find-methods generic-function (:around))
(list
(make-method-from-form
`(multiple-value-prog2
(progn ,@(mapcar #'(lambda (m) (make-method-call m))
(find-methods generic-function
(:before))))
,(make-call-first-method (find-methods generic-function)))
(progn ,@(mapcar #'(lambda (m) (make-method-call m))
(find-methods generic-function
(:after)
:most-specific-last))))))))
3) Additional Supporting macros
We also propose to provide several macros useful in many common cases
that provide an interface to these primitives.
(call-all-methods &optional (filter ())
(order :most-specific first)
(operation 'progn))
constructs a call to all methods specified combined by operation given
(call-first-method &optional(filter ())
(order :most-specific first)
form-for-last-method)
constructs a call-first-method of selected list. Selected list are
those methods matching filter, followed by a method constructed from
form-for-last-method, if the latter is non-nil
----
**New style (with supporting additional macros)
(define-method-combination2 :daemon (generic-function)
`(multiple-value-prog2
(call-all-methods (:before))
(call-first-method)
(call-all-methods (:after) :most-specific-last)))
(define-method-combination2 :around+daemon (generic-function)
`(call-first-method (:around)
(multiple-value-prog2
(call-all-methods (:before))
(call-first-method)
(call-all-methods (:after) :most-specific-last)))
(define-method-combination2 :and (generic-function)
'(call-all-methods (*) :most-specific-first and))
∂15-Oct-86 1602 DLW@ALDERAAN.SCRC.Symbolics.COM Re: Anonymous Generic Function Proposal
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 15 Oct 86 16:01:56 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 11712; Wed 15-Oct-86 18:21:12 EDT
Date: Wed, 15 Oct 86 18:27 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Re: Anonymous Generic Function Proposal
To: Gregor.pa@XEROX.ARPA
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <861014-172917-2958@Xerox>
Message-ID: <861015182712.2.DLW@CHICOPEE.SCRC.Symbolics.COM>
Line-fold: No
Given RPG's proposal, it seems to me that your alternative #2 is the
only one that can possibly be right. It's well-established elsewhere
that the meaning of a "form that does a lexical binding" is that the
form establishes an entirely new Lisp variable, completely masking any
outer use of that variable name. That is, the new variable created by
the lexical-binding form is totally unrelated to its outer namesake.
Extrapolation of this principle leads to alternative #2. If the forms
are named as proposed, they must do normal Lisp lexical binding in the
same way that flet and labels do.
∂15-Oct-86 1602 DLW@ALDERAAN.SCRC.Symbolics.COM Anonymous Generic Functions
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 15 Oct 86 16:02:33 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 11714; Wed 15-Oct-86 18:27:41 EDT
Date: Wed, 15 Oct 86 18:33 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Anonymous Generic Functions
To: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 15 Oct 86 10:51 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861015183350.3.DLW@CHICOPEE.SCRC.Symbolics.COM>
Date: 15 Oct 86 0751 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
The reason for anonymous generic functions is the same reason for
anonymous functions. The user wants to define a locally known
generic function without the possibility of other methods
leaking in.
I'm not sure what you mean by this. Consider the following example:
(defun a ()
(generic-function-labels
((foo ((x c1)) ...))
...
(b #'foo)
...
(foo ...)))
(defun b (gf)
(add-method gf ...))
This appears to be a case in which other methods have leaked in.
Perhaps you meant that the compiler can sometimes prove that no methods
have leaked in. To do so, the compiler must show that no outside
functions are called that can possibly get their paws on the generic
function object.
(The term "anonymous generic function" is a little strange in this case,
since the generic function seems be named "foo".)
Early on, the small minds didn't think FLET and LABELS would be useful,
but I see lots of user code, and lots of implementor code, using them
everywhere.
But that would be a very different justification for
generic-function-labels, namely that it's useful to have methods that
can access the lexical variables of an outer contour. Is that part of
the justification?
I'm still not wholly convinced that this is really useful. It's hard to
go into a complete description, but basically the way I've seen generic
functions used, they are mainly employeed as a modularity technique for
organizing large systems, whereas this kind of micro-use is not for that
purpose. Or something like that; I'm not explaining it well. I concede
that, as you point out, it's hard to know for sure what will turn out to
be useful. But this one's hard to evaluate.
∂15-Oct-86 1635 Masinter.pa@Xerox.COM Re: Anonymous Generic Functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Oct 86 16:34:57 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 OCT 86 16:21:20 PDT
Date: 15 Oct 86 16:21 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Anonymous Generic Functions
In-reply-to: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>'s
message of Wed, 15 Oct 86 18:33 EDT
To: DLW@ALDERAAN.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861015-162120-4109@Xerox>
"I'm still not wholly convinced that this is really useful. It's hard
to
go into a complete description, but basically the way I've seen generic
functions used, they are mainly employeed as a modularity technique for
organizing large systems, whereas this kind of micro-use is not for that
purpose. "
I was in the middle of composing a similar message. I agree; I think
your words explain it OK.
∂15-Oct-86 2018 kempf%hplabsc@hplabs.HP.COM Re: Anonymous Generic Functions
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 15 Oct 86 20:18:25 PDT
Received: from hplabsc by hplabs.HP.COM ; Wed, 15 Oct 86 19:35:13 pdt
Received: by hplabsc ; Wed, 15 Oct 86 19:35:02 pdt
Date: Wed, 15 Oct 86 19:35:02 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8610160235.AA15608@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Anonymous Generic Functions
RPG's proposal certainly does tend toward conceptual unity, in that,
you could do exactly the same things with generic
functions as with regular functions
but I tend to favor the point raised by Dan and Larry. I've
typically seen object-oriented programming used for "programming in
the medium" (as opposed to programming in the large or in the small).
Packages provide modularity on a larger scale, functions on a smaller.
In languages like Scheme, where the only unit of modularity is the
function, the conceptual unity would become more important.
Jim Kempf kempf@hplabs
∂15-Oct-86 2136 Moon@STONY-BROOK.SCRC.Symbolics.COM Method combination -- writeup for revised syntax
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 15 Oct 86 21:34:39 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 134636; Wed 15-Oct-86 23:40:46 EDT
Date: Wed, 15 Oct 86 23:39 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Method combination -- writeup for revised syntax
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861015233940.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Here is the current status of the new syntax for
define-method-combination. This is a first draft and I will likely send
some corrections tomorrow after I have implemented and tested it, and
after I have digested Danny's message on the same topic, which arrived
this evening. It also will not shock me if this evolves a little as a
result of discussion.
This differs a little from what we said in Palo Alto on Saturday,
because it turned out, on reflection, that some of the things we said
then could not actually work. I apologize for the long delay in sending
this out; part of the problem was that I was ill, and part of the problem
was that just transcribing what we said on Saturday turned out not to be
useful.
>>> CONTEXT:
When a generic function is called with particular arguments, it must decide
which method or methods to call, in which order to call them if there is
more than one, and from where to get the value(s) to return. In addition,
if CALL-NEXT-METHOD is used someone must decide which method is next.
These requirements are handled by the following 4-step procedure:
1. Select the set of available methods.
The set of available methods consists of all methods for that generic function
whose specialized parameters match their corresponding arguments.
2. Sort the available methods into a precedence order.
To compare the precedence of two methods, examine their parameter
specializers in order from left to right. An unspecialized parameter has a
default parameter specializer of T. The first pair of parameter
specializers that are not equal determine the precedence. Method X is more
specific than method Y if method X's parameter specializer is earlier than
method Y's parameter specializer in the class precedence list of the class
of the argument. Since the methods are available for this argument, it is
guaranteed that their parameter specializers are present in the class
precedence list of the class of the argument.
T is implied at the very end of each class precedence list, so it is less
specific than any other class. (QUOTE individual) is more specific than
any class.
The resulting list of available methods is sorted with the most specific
method first and the least specific method at the end.
3. Apply method combination.
The method combination technique specified for the generic function receives
the sorted list of available methods and returns a Lisp form. This form
contains calls to some or all of the methods, defines the value(s) to be
returned by the generic function, and optionally makes some of the methods
reachable via CALL-NEXT-METHOD, rather than calling them directly.
4. Consider the resulting Lisp form.
In the simplest implementation, the generic function simply evaluates the
form. In practice, this is too inefficient and most implementations do not
execute this entire procedure every time a generic function is called.
Instead they employ a variety of optimizations such as precomputation into
tables, compilation, and/or caching to speed things up. Some illustrative
examples (not exhaustive):
- Use a hash table keyed by the class of the arguments.
- Compile the Lisp form and save the resulting compiled-function.
- Recognize the Lisp form as an instance of a pattern of control structure
and substitute a closure of a function that implements that structure.
The Lisp form serves as a more general interface. For example, a tool that
determines which methods are called and presents them to the user works by
going through the above procedure and then analyzing the form to determine
which methods it calls, instead of evaluating it.
The define-method-combination facility described below allows the programmer
to customize step 3 of the above procedure without having to worry about
what happens in the other steps. The other steps of the procedure can be
customized by a more advanced programmer, using meta-objects.
The meaning of the qualifiers of a method is defined entirely by step 3 of
the above procedure. These qualifiers give the method combination
procedure a way to distinguish between methods. Because
define-method-combination controls the meaning of these qualifiers, it also
is the place to control human-readable descriptions of these qualifiers.
These descriptions are printed by tools in the programming environment,
which are not specified by this standard and are not likely to be portable,
but the descriptions themselves are easily portable and are related to the
programmer's intent in using define-method-combination, not to the
programming environment tools. A description is a format string, used by
(APPLY #'FORMAT stream description (METHOD-QUALIFIERS method)). In most
cases the description will not contain any format directives. If no
description is specified, a default description is chosen.
>>> NOTE:
This does not yet incorporate anything from Bobrow's message of 15 October.
>>> SHORT FORM:
(DEFINE-METHOD-COMBINATION name operator {keyword argument}*)
Keywords are:
:DESCRIPTION format-string
:DOCUMENTATION string
This produces a Lisp form (operator method-call method-call...).
Name and operator must be non-nil symbols. Operator can be the name of a
function, the name of a macro, or the name of a special form.
Nothing in this define-method-combination form is evaluated.
This method-combination type recognizes primary methods (methods with no
qualifiers), methods with one qualifier equal to <name>, and methods with
one qualifier equal to :around. Primary methods and <name> methods are
interchangeable. :around methods behave as in the default type of method
combination.
A method-combination type defined this way always takes one optional
argument, order, defaulting to :most-specific-first. It doesn't seem
worthwhile to add a keyword to control this or turn it off, even though it
is only useful with some operators.
PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT symbol
Tells the object system that a form (symbol form1) can be optimized to just
form1. (PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT 'PROGN) is done automatically.
Note that if symbol is a function (rather than a special operator) the
optimization is only strictly valid if form1 returns exactly one value.
This is not checked. PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT might affect the
compiler in addition to the object system, but this is implementation
dependent.
[If this never affects the compiler, then perhaps it should be changed back
to a keyword word argument to the short form and to make-method-call.]
>>> LONG FORM (BASIC FACILITIES):
(DEFINE-METHOD-COMBINATION name lambda-list ({method-selection}+)
{declaration | doc-string}*
{form}+)
name -- a non-null symbol
lambda-list -- receives the arguments in the :method-combination option to defgeneric.
method-selection -- (variable {qualifier-pattern}+ {keyword argument}*)
variable -- a non-constant symbol, which gets bound to a list of the methods
whose qualifiers match at least one of the qualifier-patterns.
(The list is possibly modified by the keywords).
qualifier-pattern -- The symbol *, which matches all methods, or a list.
Each list element is *, which matches any qualifier, or an atom,
which matches a qualifier EQL to it. The list can end in
a dotted pair whose cdr is *, which matches any number of
additional qualifiers; otherwise the number of qualifiers
must be the same as the length of the pattern. The empty
list () matches methods with no qualifiers, of course.
Keywords are:
:ORDER a form evaluating to :MOST-SPECIFIC-FIRST or :MOST-SPECIFIC-LAST.
:DESCRIPTION format-string
additional keywords mentioned under "Advanced Facilities"
The first qualifier-pattern to match a method "consumes" that method,
and later qualifier-patterns are not tested. Thus if there is more than
one method-selection, each method appears in the binding of at most one
method-selection variable.
If a method is available but matches none of the qualifier-patterns, the
fact that the method is not valid with this type of method combination is
automatically reported as an error or as a warning as appropriate.
Declarations concerning bindings can be applied to the variables in the
lambda-list but not to the variables in the method-selections. If a
doc-string is present, it documents the method-combination type. The value
of the last form in the body is the Lisp form that specifies how the
methods are combined, as discussed above.
Related functions:
MAKE-METHOD-CALL method-list &key :operator :around
Returns a form whose car is operator (default is progn) and whose cdr is
forms that call the methods. If proclaim-identity-with-one-argument of the
operator has been done, and the length of method-list is 1, returns just a
form that calls the one method. If method-list is nil, returns nil.
If around is true (default is false), returns a form that calls the first
method and arranges for call-next-method to reach the rest of the methods,
in the order they appear in method-list. In this case :operator cannot be
specified.
There are additional keywords mentioned under "Advanced Facilities".
MAKE-METHOD-FROM-FORM form
Returns an object that acts like a method whose body is the form. Informally
and imprecisely this could be described as "the method version of lambda".
METHOD-QUALIFIERS method
Returns a list of the method's qualifiers. This is particularly useful
when the qualifier-pattern contains *s, to find what they matched.
METHOD-COMBINATION-ERROR format-string &rest args
Either signals an error or prints a warning, depending on context. Adds
contextual information to the message. This should be used instead of
ERROR or WARN to signal errors, such as too many or too few methods
defined, because the type of error message appropriate in a given situation
is a function of the programming environment. Using this abstraction
ensures portability.
>>> LONG FORM (ADVANCED FACILITIES):
These have been separated from the basic facilities because they are not
needed in order to understand the basic idea. I am proposing that each of
these should be included in the standard, but we can decide about them on a
case by case basis.
WRAP-AROUND-METHODS around-methods form
A combination of make-method-call and make-method-from-form that puts
:around methods around a form. This only exists for convenience, to
encourage programmers of new method-combination types to support :around
methods.
(defun wrap-around-methods (around-methods form)
(if around-methods
(make-method-call (append around-methods
(list (make-method-from-form form)))
:around t)
form))
Additional keywords for method-selections in define-method-combination:
:INCLUDE-DEFAULT-METHODS boolean
If :include-default-methods is true, then this method-selection receives
the additional qualifier-pattern (:DEFAULT), but methods that match that
pattern are discarded unless no methods match any of the other
qualifier-patterns of this method-selection. This is a way to have
methods that are less specific than all other methods, regardless of
the class precedence order.
:SELECT one of :FIRST, :LAST, :EVERY, or :REMOVE-DUPLICATES
Discards some of the methods that match the qualifier-patterns. The
default is :every, which retains all of the methods. :First and :last
discard all but the first or last method. :Remove-duplicates identifies
methods that have equal qualifiers and discards all but the first method in
each group. :Select is an abbreviation for code that could be written less
concisely, as follows:
:first -- (setq var (and var (list (first var))))
:last -- (setq var (last var))
:remove-duplicates --
(setq var (remove-duplicates var :from-end t
:key #'method-qualifiers
:test #'equal))
Make-method-call with just a method object instead of a list of one
element would be a convenience sometimes and appears to be harmless.
Additional keywords for make-method-call:
:ARGLIST list of forms
Uses the specified forms as the arguments to each method instead of
using the arguments to the generic function.
:APPLY list of forms
Same as :arglist except that the last form in the list evaluates to
a list of arguments and the call is made with apply rather than funcall.
You must not specify both :arglist and :apply.
This is a bit more complicated than it seems at first, because there are
three potentially different argument lists involved. (1) The arguments
supplied to the generic function. (2) The arguments passed from the
generic function to the methods. (3) The arguments actually received by a
method. (2) differs from (1) in certain proposals for discrimination on
optional arguments, such as the &generic-optional one and the :interface
one. (3) differs from (2) in implememtations that have a special calling
sequence for methods. The :arglist/:apply keywords for make-method-call
allow you to change the (2) arguments; any implementation-dependent
transformation from (2) to (3) still applies.
It is not a good idea to change arguments that are used for discrimination,
since this could cause a method to be called with an argument that does
not match its parameter specializer.
(WITH-METHOD-ARGUMENT-ACCESSORS lambda-list &body body)
This macro is convenient when changing the arguments passed to the methods.
Each parameter in lambda-list is bound to a form that accesses the
corresponding method argument, and then body is executed. These accessor
forms come from the hidden information mentioned above. Lambda-list must
match the (2) arguments mentioned above.
>>> PRIMITIVE FUNCTIONS:
[Not yet written, this section would define primitive functions that are
used in the expansion of the above convenience macros. This is probably
really part of the meta-object protocol. For example, define-method-combination
might expand into a defclass and two defmethods, one for the combining and
the other for the qualifier descriptions.]
>>> DESIGN RATIONALE:
The functions make-method-call and make-method-from-form exist not only for
convenience, but to conceal the implementation-dependent method calling
sequence details. This gives implementations the freedom to do special
optimizations, which may depend on the argument list of the generic
function and on the particular set of available methods. This will become
especially important if in the future we allow discrimination on optional
arguments.
The functions make-method-call and make-method-from-form can only be called
from the body forms of define-method-combination. Their operation depends
on hidden state variables that contain the implementation-dependent calling
sequence details. It seems cleaner to hide this stuff completely, by
passing it around the user's method-combination routine in dynamic
variables, rather than making it visible as an argument to the user's
method-combination routine.
Why package everything into make-method-call, rather than providing several
functions? It seemed cleaner to put it all into one, and use keyword
arguments to provide variations, rather than making up a lot of different
names, but this is not an essential point.
Why have a :around keyword to make-method-call, instead of using
:operator with a macro that does the call-next-method stuff? The
latter technique is not as flexible because it doesn't have access
to the method meta-objects, only to the Lisp forms that invoke the
method functions. Note that we have avoided specifying anything
about those Lisp forms; they are completely implementation-dependent
to allow maximum freedom for optimization.
>>> EXAMPLES:
(define-method-combination :daemon (&optional (order ':most-specific-first))
((around (:around))
(before (:before))
(primary () :order order)
(after (:after) :order :most-specific-last))
;; Must have a primary method
(unless primary
(method-combination-error "A primary method is required."))
(wrap-around-methods around
`(multiple-value-prog2
,(make-method-call before)
,(make-method-call primary :around t)
,(make-method-call after))))
(define-method-combination :inverse-list ()
((around (:around))
(methods () (:inverse-list)))
(with-method-argument-accessors (instance list)
(wrap-around-methods around
(cons 'progn
(loop for (method . rest) on methods
collect (make-method-call method :arglist (list instance list))
when rest collect `(pop ,list))))))
(define-method-combination :simplified-case ()
((around (:around))
(methods (*) :select :remove-duplicates))
(with-method-argument-accessors (instance subtype &rest args)
(wrap-around-methods around
`(ecase ,subtype
,@(mapcar #'(lambda (method)
(list (method-qualifiers method)
(make-method-call method :apply (list instance args))))
methods)))))
∂16-Oct-86 1118 Moon@STONY-BROOK.SCRC.Symbolics.COM Anonymous Generic Function Proposal
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 16 Oct 86 11:17:42 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 135071; Thu 16-Oct-86 12:54:20 EDT
Date: Thu, 16 Oct 86 12:53 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Anonymous Generic Function Proposal
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 14 Oct 86 19:59 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>,
<861014-172917-2958@Xerox>,
The message of 15 Oct 86 10:51 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>,
<861015182712.2.DLW@CHICOPEE.SCRC.Symbolics.COM>,
<861015183350.3.DLW@CHICOPEE.SCRC.Symbolics.COM>,
<861015-162120-4109@Xerox>,
<8610160235.AA15608@hplabsc>
Message-ID: <861016125310.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
This seems like a great idea to experiment with. Is this an entirely
new idea, or is it based on experience in a real system (not necessarily
a Common Lisp system)? If there isn't some real basis in experience,
I think it would be highly premature to cast it in concrete in a standard.
Is there anything in the current proposed standard that would make it
difficult to add this feature?
∂16-Oct-86 1837 Gregor.pa@Xerox.COM Anonymous Generic Function Proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 16 Oct 86 18:37:30 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 16 OCT 86 18:37:13 PDT
Date: Thu, 16 Oct 86 18:37 PDT
From: Gregor.pa@Xerox.COM
Subject: Anonymous Generic Function Proposal
To: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <861016183705.2.GREGOR@AVALON.isl.parc.xerox.com>
Line-fold: no
I wasn't questioning the usefulness of generic-function-labels. Rather
I was pointing out that there were two different kinds of binding of
generic functions (or their parts) that were useful.
One kind of binding, the one which I called #2 and which I will now call
GFLABELS, says that within the scope of the GFLABELS the symbol names a
generic function with only the set of methods given in the GFLABELS.
This one gets its name because it binds an entire generic function.
Given GENERIC-LAMBDA, it is straightforward to implement GFLABELS and
GFLET as macros which expand into labels and flet.
(gflabels ((foo ((x boat) <boat body>)
((x plane) <plane body>)))
body)
(labels ((foo (x) (funcall
#'(generic-lambda ((x boat) <boat body>)
((x plane) <boat body>))
x)))
body)
The other kind of binding, the one I called #1 and which I will now call
MLABELS, says that within the scope of the MLABELS there should be some
extra methods on the generic function which existed outside the scope of
the MLABELS. This one gets its name because it binds methods on a
generic function.
On the whiteboard, Danny and I have convinced ourselves that
implementing MLABELS is not hard, but it isn't quite as easy as
gflabels.
But working it out brought up some interesting questions, including a
questions about what mlabels should do in the following case.
(defmethod move ((b boat)) 'outer-boat)
(defun make-special-mover ()
(mlabels ((move ((b boat)) 'inner-boat))
#'(lambda (o) (move o))))
(setq special-mover (make-special-mover))
Now:
(funcall special-mover (make 'fast-boat))
clearly returns inner-boat.
But if I do:
(defmethod move ((fb fast-boat)) 'outer-fast-boat)
should (funcall foo (make 'fast-boat)) return outer-fast-boat?
-------
∂16-Oct-86 1922 Masinter.pa@Xerox.COM Re: Summary of Object Standard Discussions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 16 Oct 86 19:19:21 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 16 OCT 86 19:19:19 PDT
Date: 16 Oct 86 19:19 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Summary of Object Standard Discussions
In-reply-to: Bobrow, Gregor's message of 8 Oct 86 15:50 PDT
To: COMMON-LISP-OBJECT-SYSTEM@SAIL.STANFORD.EDU
Message-ID: <861016-191919-5358@Xerox>
I know you've been over this, but I'm still bothered by a few things in
the defclass syntax.
In DEFCLASS syntax, isn't it a bit odd to have the :DOCUMENTATION down
at the bottom of the form after all of the superclass and all of the
slots and everything?
(DEFCLASS FOO (A B C)
(SLOT1 12)
(SLOT2 13)
:DOCUMENTATION "This is the class for FOO's"
)
Wouldn't it be more like the rest of Common Lisp (DEFUN DEFMACRO DEFTYPE
DEFVAR DEFPARAMETER DEFCONSTANT) to allow the documentation as a string
without a keyword up at the top somewhere, like
(DEFCLASS FOO (A B C) "Here's the documentation string"
...)
∂16-Oct-86 2044 Moon@STONY-BROOK.SCRC.Symbolics.COM Anonymous Generic Function Proposal
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 16 Oct 86 20:43:48 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 135071; Thu 16-Oct-86 12:54:20 EDT
Date: Thu, 16 Oct 86 12:53 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Anonymous Generic Function Proposal
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 14 Oct 86 19:59 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>,
<861014-172917-2958@Xerox>,
The message of 15 Oct 86 10:51 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>,
<861015182712.2.DLW@CHICOPEE.SCRC.Symbolics.COM>,
<861015183350.3.DLW@CHICOPEE.SCRC.Symbolics.COM>,
<861015-162120-4109@Xerox>,
<8610160235.AA15608@hplabsc>
Message-ID: <861016125310.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
This seems like a great idea to experiment with. Is this an entirely
new idea, or is it based on experience in a real system (not necessarily
a Common Lisp system)? If there isn't some real basis in experience,
I think it would be highly premature to cast it in concrete in a standard.
Is there anything in the current proposed standard that would make it
difficult to add this feature?
∂16-Oct-86 2114 Moon@STONY-BROOK.SCRC.Symbolics.COM Method Combination
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 16 Oct 86 21:12:51 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 135160; Thu 16-Oct-86 14:23:02 EDT
Date: Thu, 16 Oct 86 14:21 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Method Combination
To: Common-Lisp-Object-system@SAIL.STANFORD.EDU
In-Reply-To: <861015-144104-3961@Xerox>
Message-ID: <861016142151.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 15 Oct 86 14:39 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>,gregor.pa@Xerox.COM
This message contains a proposal for some primitives that we claim allow
simplification of the defining form for method combination. With these
primitives, we then define some standard method combination types for
examination and comment.
This will be a long reply, both because I don't want to delete any of your
original and because there are several different issues raised here.
1) Finding the methods with appropriate qualifiers. Use of this
primitive would replace the current 3rd argument to
define-method-combination.
Methods of a generic function have a list of qualifiers consisting of
all the items <qualifier> in the defining form:
(defmethod <generic-function> {<qualifier>}* ... )
The primary method has qualifier list (). find-methods uses a filter
argument that is a list. In matching, the qualifier list must be equal
to the filter list, except that * in the filter list matches any item in
the qualifier list.
(find-methods generic-function
&optional (filter ())
(order :most-specific-first))
Selects methods of the generic function that match
filter. Returns a list of such methods ordered
by specificity determined by order.
filter = ({<qualifier>|*}*)
order = :most-specific-first | :most-specific-last
examples:
(find-methods generic-function) ;; primary methods in usual order
(find-methods generic-function (:before))
(find-methods generic-function (:after) :most-specific-last)
I don't understand why this takes a generic-function as an argument,
since the set of methods that should be searched is not all the methods
defined for the generic function, but the "available methods" as defined
in the context part of the writeup I sent yesterday (which was based on
the discussion we had in Palo Alto about where method combination fits
into the scheme of things). Also, later in your proposal that argument
to find-methods seems to fade away, so I'm not sure what it's about.
The set of available methods could be passed to the method-combination
function as an explicit argument and then passed to find-methods.
That's really what happens in the primitives underlying the syntactic
sugar of Flavors' define-method-combination and my proposed new one that
I mailed out yesterday. I'm not sure what is the advantage of making
this visible to the user. Could you comment on this?
There is another problem with this find-methods function, though.
This is the problem of methods with qualifiers that don't match any
pattern (or filter in the terminology you used just above). It's
important to signal an error for such methods, rather than just dropping
them on the floor, or users will have hard-to-find bugs. Consider
the typo (defmethod blatz :bfeore ((x c1) &optional y) ...).
It looks like it would be awkward to detect and signal such an error in
your proposal, because the set of possible qualifier patterns is not
enumerated in any one place. This is reminiscent of problems we had
with the Old Flavors way of doing define-method-combination. Possibly
some code analysis of the method-combination function could find all the
calls to the find-methods function, but I'd like to see a specific
proposal before believing that that could work, and anyway this does not
seem in the spirit of your proposal. You didn't give any rationale, but
I assume the reason for proposing a find-methods function rather than
using subforms of a special form is to allow the user to do find-methods
in subroutines called from a method-combination function. Have I correctly
guessed what you had in mind? Could you comment on the reasons for
part 1 of your proposal?
Another problem is that you haven't provided a way to find methods based
on the "OR" of two or more filters (patterns). If it is necessary to do
this, it would have to be done by making separate calls to find-methods
and then merging the resulting lists to get the methods back into
precedence order, but you haven't provided the necessary primitive to
compute the precedence order. "OR"ing of patterns is fairly common
in Flavors programs.
A less serious problem is that this imperative style, rather than the
Flavors declarative style, of selecting from among the available methods
doesn't provide any place to hang additional information about the sets
of methods, such as the :description. A separate facility would have
to be developed for that, which would be awkward but certainly not
impossible.
I think a lot of what's going on with part 1 of your proposal, which I
think may be separate from the other two parts, is a difference in
style. You prefer to provide imperative interfaces so the programmer
can feel the bits between his toes. I prefer to provide declarative
interfaces so the programmer can't overlook the little details that make
things work, like error checking. Is this a fair characterization of
what's going on?
2) Primitives for constructing method combination forms. These are
designed to be used in the expression that constructs the body of a
combined method.
(make-method-call method-object)
Constructs a lisp form that calls
method-function of method-object
(make-call-first-method method-list)
Constructs a call of first method on method-list
with remainder of method-list
accessible to call-next-method.
(method-from-form lisp-form)
Constructs a method from a Lisp form for a particular generic
function.
Except for syntactic issues such as spellings of names and whether
make-method-call and make-call-first-method are two different functions
or one function with a keyword argument, these are the same as what I
am proposing. I am not at all sure that the syntax of what I am proposing
is best, so I'd like to see a discussion of the pros and cons of the
syntactic issues. To start it off, here are some questions:
1. Do we need a function for calling a single method, as in this
proposal and in Flavors, or do we only need a function that takes
a list of methods, as in my proposal?
2. Should the function that knows how call-next-method works be a
separate function or should it be combined with another function?
3. What's the best naming convention to make it clear that we are
constructing forms that call methods, rather than directly calling
methods?
4. Is it better to say (make-method-calls method-list) or
(cons 'progn (mapcar #'make-method-call method-list))?
----
We can now compare the current syntax for method combination with this
new style using the primitives given:
**Current style:
(define-method-combination1 :daemon ()
((before :every :most-specific-first (:before))
(primary :every :most-specific-first ())
(after :every :most-specific-last (:after)))
`(multiple-value-prog2
(call-component-methods before)
(call-component-method (car primary) (cdr primary))
(call-component-methods after)))
For some value of current. This is neither what I am proposing
nor what New Flavors has.
----
**New style (without supporting additional macros)
(define-method-combination2 :daemon (generic-function)
`(multiple-value-prog2
(progn ,@(mapcar #'(lambda (m) (make-method-call m))
(find-methods generic-function (:before))))
,(make-call-first-method (find-methods generic-function)))
(progn ,@(mapcar #'(lambda (m) (make-method-call m))
(find-methods generic-function
(:after)
:most-specific-last)))
(define-method-combination2 :around+daemon (generic-function)
(make-call-first-method
(append
(find-methods generic-function (:around))
(list
(make-method-from-form
`(multiple-value-prog2
(progn ,@(mapcar #'(lambda (m) (make-method-call m))
(find-methods generic-function
(:before))))
,(make-call-first-method (find-methods generic-function)))
(progn ,@(mapcar #'(lambda (m) (make-method-call m))
(find-methods generic-function
(:after)
:most-specific-last))))))))
3) Additional Supporting macros
We also propose to provide several macros useful in many common cases
that provide an interface to these primitives.
(call-all-methods &optional (filter ())
(order :most-specific first)
(operation 'progn))
constructs a call to all methods specified combined by operation given
(call-first-method &optional(filter ())
(order :most-specific first)
form-for-last-method)
constructs a call-first-method of selected list. Selected list are
those methods matching filter, followed by a method constructed from
form-for-last-method, if the latter is non-nil
----
**New style (with supporting additional macros)
(define-method-combination2 :daemon (generic-function)
`(multiple-value-prog2
(call-all-methods (:before))
(call-first-method)
(call-all-methods (:after) :most-specific-last)))
(define-method-combination2 :around+daemon (generic-function)
`(call-first-method (:around)
(multiple-value-prog2
(call-all-methods (:before))
(call-first-method)
(call-all-methods (:after) :most-specific-last)))
(define-method-combination2 :and (generic-function)
'(call-all-methods (*) :most-specific-first and))
This is an admirable attempt at brevity, but I'm having some trouble
understanding it because there aren't any commas in these backquotes.
The big advantage here seems to be elimination of the intermediate
variables used to hold lists of methods, which increases the
conciseness. On the other hand, the last example suffers a bit from
using positional arguments rather than keyword arguments, and also I'm
not sure what that asterisk is doing there. Maybe it's attempting to
paper over the lack of "OR" patterns?
For comparison, here is how the proposal I sent yesterday would
implement the same functionality (as far as I can figure out the
functionality you're implementing):
(define-method-combination :daemon ()
((before (:before))
(primary ())
(after (:after) :order :most-specific-last))
;; Must have a primary method [does your proposal do this?]
(unless primary
(method-combination-error "A primary method is required."))
`(multiple-value-prog2
,(make-method-call before)
,(make-method-call primary :around t)
,(make-method-call after)))
(define-method-combination :around+daemon ()
((around (:around))
(before (:before))
(primary ())
(after (:after) :order :most-specific-last))
;; Must have a primary method
(unless primary
(method-combination-error "A primary method is required."))
(wrap-around-methods around
`(multiple-value-prog2
,(make-method-call before)
,(make-method-call primary :around t)
,(make-method-call after))))
(define-method-combination :and ()
((methods (*)))
(make-method-call methods :operator 'and))
Removing the intermediate variables definitely makes the syntax more
concise, in the cases where the additional supporting macros you
propose apply. I'm having trouble judging whether it's more understandable,
and there are the issues of whether it can be made to work that I
brought up in part 1. Right now I still feel that the variables are
necessary, but we can keep discussing this.
I added this section to the proposal I mailed out yesterday. Is this
an accurate summary of the issues?
>>> ISSUES:
Brought up by Bobrow's message of 15 October and Moon's message of 16 October.
(1) Should there be a declarative thing that binds variables to lists
of methods, or should that be done imperatively? (Moon's message lists
some problems with the imperative approach).
(2) Can the method-selections and the forms be combined into a template
(built up from macros?) that puts the method-selections right where
the method-calls will go in the result?
(3) Naming and syntax of functions such as make-method-call.
(4) "OR" qualifier-patterns.
∂16-Oct-86 2220 Moon@STONY-BROOK.SCRC.Symbolics.COM Dispatching on optional/keyword arguments
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 16 Oct 86 22:18:52 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 135694; Fri 17-Oct-86 00:49:34 EDT
Date: Fri, 17 Oct 86 00:48 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Dispatching on optional/keyword arguments
To: MMcM@STONY-BROOK.SCRC.Symbolics.COM,
Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861017004826.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
MMcM asked me what was so hard about dispatching on optional and keyword
arguments (i.e. allowing methods to specify classes for such arguments).
I went back through the mail and found eight proposals for coping with
this that have been mentioned so far; this message is an attempt to
classify them. I included proposals that seemed to have been rejected
already, since the idea was to summarize all the thinking that has
gone on.
There were also a bunch of mutually inconsistent requests from different
users for what the semantics should be, which Gregor collected, but I'm
not going to repeat those here. Ask me, Mike, if you want to see them.
The problems all have to do with what happens when an optional argument
is not supplied by the caller of the generic function, but one or more
methods exist that are selected by the class of that argument.
Matrix of proposal characteristics:
Proposal # 1 2 3 4 5 6 7 8
can discriminate on optionals yes yes yes yes yes yes no sort-of
can discriminate on keyword args yes yes ? yes y? yes no ?
methods can tell which args were no no yes no no yes yes yes
supplied using supplied-p parameters
(among args used for discrimination)
defgeneric has to specify which args * yes yes no no no n/a no
are used for discrimination
(* auxiliary function specifies it)
default forms appear in defmethod no no no no yes yes n/a yes
for args used for discrimination
default forms appear in defmethod yes yes y? no yes yes yes yes
for args not used for discrimination
defaults specified in more than one no no no no yes yes no no
place, so can be inconsistent or
consistency has to be defined and
enforced (defining it is harder than
we thought at first)
default value forms can be evaluated no no no no no yes no no
twice, so must not have side effects,
even when only one method gets called
all methods have consistent number yes yes yes yes yes yes no no?
of required & optional arguments
all methods have to have the same no no yes n/a no no no no
supplied-p parameters
new lambda-list syntax introduced no no yes no no no no no
peculiar semantics no no no no yes no no yes
arglist supplied by caller differs yes yes no no no no no no
from arglist written in defmethod
number of user-visible function names 2 1 1 1 1 1 1 1
all programs can be written with yes yes yes no yes yes yes yes
defmethod instead of defun (creating
a default method) because defmethod
supports all the same lambda-list
features that defun supports
The proposals, briefly:
1. Do nothing. User has to define an auxiliary function that receives the
optional arguments, defaults them, and calls the generic function, which
receives them as required arguments. This is what is, in effect, in the
draft standard proposal today.
2. Generic function receives and defaults the optional arguments, then
passes them to the methods as required arguments. The :method-arguments
option to defgeneric specifies what arguments get passed to the methods,
possibly including defaulted optionals and supplied-p parameters.
(Same as #1 except there is only one function name.)
3. Generic function receives and defaults the optional arguments, then
passes them to the methods as required arguments. This is enabled by using
&generic-optional instead of &optional in the defgeneric and defmethod
lambda-lists. In defgeneric it specifies a default form, in defmethod it
specifies no default form.
4. Generic function receives and defaults the optional arguments, then
passes them to the methods. Defmethod lambda-list isn't allowed to use
default forms or supplied-p parameters in its optionals.
5. Generic function defaults however many arguments are needed to
discriminate, depending on the particular methods that exist, and passes
those along to the methods.
6. Generic function defaults however many arguments are needed to
discriminate, depending on the particular methods that exist, but
passes only the originally supplied arguments to the methods.
7. Defgeneric specifies only the required arguments. Each method can
have different optional arguments, but they can't be used for
discrimination.
8. Discrimination only looks at the supplied arguments. If a method
specifies a class for an optional argument, that method is never called
unless that argument is supplied.
∂17-Oct-86 0515 DLW@ALDERAAN.SCRC.Symbolics.COM Anonymous Generic Function Proposal
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 17 Oct 86 05:15:02 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 12101; Fri 17-Oct-86 08:13:38 EDT
Date: Fri, 17 Oct 86 08:19 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Anonymous Generic Function Proposal
To: Gregor.pa@XEROX.ARPA, Common-Lisp-Object-System@Sail.stanford.edu
In-Reply-To: <861016183705.2.GREGOR@AVALON.isl.parc.xerox.com>
Message-ID: <861017081952.1.DLW@CHICOPEE.SCRC.Symbolics.COM>
Line-fold: No
Date: Thu, 16 Oct 86 18:37 PDT
From: Gregor.pa@Xerox.COM
The other kind of binding, the one I called #1 and which I will now call
MLABELS, says that within the scope of the MLABELS there should be some
extra methods on the generic function which existed outside the scope of
the MLABELS. This one gets its name because it binds methods on a
generic function.
Note that this one is dynamic in scope, whereas GFLABELS is lexical in
scope. In fact, your MLABELS resembles dynamic variable binding more
than anything else. You would presumably want to to be defined that
THROWing out of an MLABELS undoes the changes to the generic function,
as if there were an UNWIND-PROTECT handler, right?
It seems that you could implement such a thing out of existing
primitives, as a macro, using ADD-METHOD and REMOVE-METHOD and
UNWIND-PROTECT, except that you'd have to keep track of all
the shadowing manually which would be a bit of a drag.
On the other hand, your example indicates that you expect a closure to
close over the changes made to the generic function. This looks like a
weird combination of lexical and dynamic behavior. When a closure is
called, normally it just reinstantiates a binding environment; it
doesn't go around doing things like side-effecting generic function
objects.
However, if you really were to imagine things working this way, then I
think your example has to return outer-fast-boat, on the grounds that
the closure invocation provides a new handler for "move" on "boat", but
it still gets shadowed by "fast-boat"'s handler, in the usual way.
∂17-Oct-86 0948 masinter.PA@Xerox.COM Re: Dispatching on optional/keyword arguments
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Oct 86 09:47:55 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 17 OCT 86 09:20:47 PDT
From: masinter.PA@Xerox.COM
Date: 17 Oct 86 9:20:00 PDT
Subject: Re: Dispatching on optional/keyword arguments
In-reply-to: Moon@STONY-BROOK.SCRC.Symbolics.COM's message of Fri, 17
Oct 86 00:48 EDT, <861017004826.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
To: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
cc: MMcM@STONY-BROOK.SCRC.Symbolics.COM,
Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861017-092047-5784@Xerox>
Thank you for the summary. The only "characteristic" which seems dubious
is "peculiar semantics" -- it is hardly objective.
We might want to see how much agreement there is on which
characteristics are positive and which are negative. For example, I
think that it is positive if methods are not required to have congruent
argument lists unnecessarily -- it encourages modularity if you need not
know much about the other methods before writing a new one.
Others clearly disagree.
∂17-Oct-86 1037 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Oct 86 10:37:29 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 17 OCT 86 09:58:06 PDT
Date: 17 Oct 86 09:57 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Anonymous Generic Function Proposal
In-reply-to: Gregor.pa's message of Thu, 16 Oct 86 18:37 PDT
To: Gregor.pa@Xerox.COM
cc: Common-Lisp-Object-System@Sail.stanford.edu
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861017-095806-5846@Xerox>
But working it out brought up some interesting questions,
including a questions about what mlabels should do in the following
case.
(defmethod move ((b boat)) 'outer-boat)
(defun make-special-mover () (mlabels ((move ((b boat))
'inner-boat))
#'(lambda (o) (move o))))
(setq special-mover (make-special-mover))
Now:
(funcall special-mover (make 'fast-boat))
clearly returns inner-boat.
But if I do: (defmethod move ((fb fast-boat))
'outer-fast-boat)
should (funcall foo (make 'fast-boat)) return outer-fast-boat?
I believe the semantics of MLET ought to be that on entry to the lexical
scope, the outer generic function is copied, and a new generic function
with the added methods is created. It is this new generic function that
is lexically bound to the mlet variable (move in this case). Thus, for
Gregor's example, (funcall foo (make 'fast-boat)) should still return
inner-boat. But reentering the lexical scope above should create a new
special-mover that does return outer-fast-boat.
-- danny
∂17-Oct-86 1037 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Oct 86 10:37:43 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 17 OCT 86 10:34:58 PDT
Date: 17 Oct 86 10:34 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Anonymous Generic Function Proposal
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 16 Oct 86 12:53 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861017-103458-5895@Xerox>
This seems like a great idea to experiment with. Is this an
entirely new idea, or is it based on experience in a real system
(not necessarily a Common Lisp system)? If there isn't some real
basis in experience, I think it would be highly premature to cast
it in concrete in a standard. Is there anything in the current
proposed standard that would make it difficult to add this feature?
The semantics of anonymous generic functions are clearly available in
the new standard. One creates such a generic-function object, and does
add-methods. The question is whether we provide a simple syntax for this
use. It seems to me that we should at least consider such a syntax. I
think the feature would be as useful as flet and labels, with which we
have had significant experience.
An alternative syntax would oveload flet and flabels with a keyword as
shown in the following examples. It allows mixing of different kinds of
function. Its principal disadvantage compared to gflabels etc is that
it must be recognized at a diffeent level rather than be a macro that is
expanded.
(defun foo ()
(flet ((bar :generic ;bar is a generic function
(((x plane) (y boat)) bar-method-1)
(((x boat) (y plane)) bar-method-2))
(baz (x y) ..) ; baz is an ordinary function
(zed :methods ; locally adds methods to global
zed
((q truck)) zed-method-1) ; to define a local zed
((r cycle)) zed-method-2)))
...))
(defun foo ()
(labels ((bar :generic
((x plane) (y boat) method-1)
((x boat) (y plane) method-2))
(baz (x y) ..))
...
))
∂17-Oct-86 1237 kempf%hplabsc@hplabs.HP.COM Re: Method Combination
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 17 Oct 86 12:37:16 PDT
Received: from hplabsc by hplabs.HP.COM ; Fri, 17 Oct 86 09:11:02 pdt
Received: by hplabsc ; Fri, 17 Oct 86 09:09:27 pdt
Date: Fri, 17 Oct 86 09:09:27 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8610171609.AA05574@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Method Combination
I looked over both Dave and Danny's proposals and thought I'd
throw out some comments. Not having ever used Flavors and the
old style method combination, these comments are definitely from
a naive user, so if only comments from experts are desired, please
ignore the rest of this message.
The CONTEXT: section of Dave's proposal was particularly helpful
in clarifying what exactly is going on when a method is called.
In particular, I like the idea of method combination being a
way of customizing method invocation without having to hack the
metaobject protocol. The relationship with the :INTERFACE option
to DEFGENERIC still needs clarification, however. Perhaps the
:INTERFACE option, method combination, and creation of customized
generic function metaclasses could be seen as ways of declaratively
modifying method invocation which demand increasing sophistication
on the part of the programmer.
In general, I think that Danny's proposed syntax is somewhat cleaner,
though, not being an expert, there may be fine points which I'm missing.
I particularly like the functional approach in which FIND-METHOD
avoids introduction of identifiers, and the further simplification
which the additional macros provide.
Jim Kempf hplabs!kempf
∂17-Oct-86 1430 RPG Re: Anonymous Generic Function Proposal
∂14-Oct-86 1849 Masinter.pa@Xerox.COM Re: Anonymous Generic Function Proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Oct 86 18:48:57 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 OCT 86 17:26:06 PDT
Date: 14 Oct 86 17:25 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Anonymous Generic Function Proposal
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 14 Oct 86
16:59 PDT
To: RPG@SAIL.STANFORD.EDU
Message-ID: <861014-172606-2956@Xerox>
Howcum no TO in your proposal?
Can you motivate this? I see absolutely no need for it, beside some
small-minded notion of "completion".
Just because we could extend generic functions to a LABELS equivalent
doesn't mean we should.
∂17-Oct-86 1652 Masinter.pa@Xerox.COM Re: Dispatching on optional/keyword arguments
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Oct 86 16:52:12 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 17 OCT 86 16:35:50 PDT
Date: 17 Oct 86 16:35 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Dispatching on optional/keyword arguments
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 17 Oct 86 00:48 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: MMcM@STONY-BROOK.SCRC.Symbolics.COM,
Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861017-163550-6338@Xerox>
Since I favor proposal 8, I checked your chart just for that column.
I think the answers are
yes yes yes no no yes yes no no no no no no 1 yes
Your chart gave
sort-of ? yes no yes yes no no no? no no yes no 1 yes
I haven't checked the other columns, however.
∂17-Oct-86 1845 @MC.LCS.MIT.EDU:Moon@VALLECITO.SCRC.Symbolics.COM "Classes" Document and Agreements Summary
Received: from MC.LCS.MIT.EDU by SAIL.STANFORD.EDU with TCP; 17 Oct 86 18:45:18 PDT
Received: from VALLECITO.SCRC.Symbolics.COM by MC.LCS.MIT.EDU 17 Oct 86 21:24:38 EDT
Received: from EUPHRATES.SCRC.Symbolics.COM by VALLECITO.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 59948; Fri 17-Oct-86 17:45:12 EDT
Date: Fri, 17 Oct 86 17:45 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: "Classes" Document and Agreements Summary
To: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
cc: common-lisp-classes-discussion@mc.lcs.mit.edu,
snyder%hplabsc@hplabs.HP.COM
In-Reply-To: <8610092255.AA05179@hplabsc>
Message-ID: <861017174507.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 9 Oct 86 15:55:24 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
I read through the "Classes" document in detail, and the executive
summary posted by Danny on Oct. 8. Below is a list of detailed
questions, comments, and corrections which I noticed.
I was hoping to see some discussion stimulated by this. However, it's
been a week and nothing has happened. Maybe if I make a few replies and
provocative comments I can start something off. Also your comments
should be pretty helpful to us in refining the new document now being
developed.
I'm going to delete some parts of your message where I have nothing
useful to say, as some sort of minimal gesture toward brevity.
You'll probably get two copies of this message, because I'm sending it
to you directly just on the off-chance that you're not on the mailing
list yet.
*Does method combination go through the generic function or
through the method itself? If the former, then couldn't method
combination be done using macros? If the latter, then obviously
not.
I couldn't get anything out of this other than the message that you are
confused by the document. The next version of the document should be
much less confusing, so let's defer this until then.
COMMENTS (page numbers reference the "Classes" document)
pg. 5-CLASS-OF/TYPE-OF relationship needs some clarification
for instance objects. What will TYPE-OF return when applied
to an instance object? See comment below on TYPEP
Every object is an instance. If you mean what does TYPE-OF return
when given an object created by (MAKE-INSTANCE class-name), it
returns class-name. CLASS-OF returns the actual class object.
pg. 5-:CLASS option-Is this for class slots? If so, it seems
to be a retraction of some earlier discussion about doing
this in the metaclass. What about inheritance of class
slots? Are seperate copies of class state maintained in
the super and subclass objects or not?
We need either to resolve the unclarities in the :ALLOCATION
slot option or to remove that option from the standard for
the time being; implementations can always add it as an
extension for experimentation purposes.
pg. 7-Presumably (TYPE-OF <object>) -> <class-name> for
TYPEP to work correctly?
I never heard of an implementation of TYPEP that worked by
calling TYPE-OF. However, I think we are specifying that TYPE-OF
returns that value.
pg. 7-How is automatic updating of instances done when it is
redefined? Are there any hooks for user defined transformation
of instance state? For class state (re. :CLASS option above)?
Is there some way for a user to override this?
The working group hasn't discussed this yet, but we ought to.
One thing to look at (except for class variables) is the way
Flavors does it. There is a hook for user defined transformation.
Somewhere I have a collection of user comments on its deficiencies,
which we should look at.
Consider the
case of developing extensions to a programming environment
while using the environment. One might not want old instances
of a redefined class to be updated, if the behavior of the
redefined class was not yet solid; otherwise, the environment
might break.
I think if you want to redefine a class without redefining it you should
give it a different name, perhaps using packages. In Old Flavors we
found lots of subtle reasons why just detaching the old instances from
the class structure and letting them continue to use the old class
doesn't really work (mainly having to do with whether redefining a
method should replace the old definition).
pg. 14-The term "setf-lambda-list" appears to be used differently in
the middle and at the end of the page. In the middle, the term means
a qualified list, at the end, not.
The middle of the page is talking about defmethod and the end of the page
is talking about defgeneric. I think it's customary for these syntactic
meta-variables to be local to the description of one function. Maybe in
this case the reuse of the name is confusing and one of the names should
be changed--but that might be confusing, too, since they are closely
related.
pg. 15-DECLARE should be :DECLARE
No, this is the same DECLARE as in DEFUN.
pg. 15-For the :ARGUMENT-PRECEDENCE-ORDER, what happens if not
all the parameters are included?
The latest version says each required parameter should be included.
I assume that means it signals an error if you leave one out.
pg. 17-I presume the :CLASS option was included so that lambda
list parameters which were not qualified could be opened up using
the WITH-SLOTS special form. If so, then why allow super class names
as well? Isn't it rather more appropriate to have the name following
:CLASS designate a class or any subclass, as with the class qualifiers
in the lambda list?
I think you exchanged sub- and super-class somewhere along the way.
I find that terminology confusing, too. Both in WITH-SLOTS :CLASS and
in DEFMETHOD parameter specializers, (TYPEP object class) is true;
in other words, class can be a superclass of (CLASS-OF object).
And what if the parameter isn't of that class
at runtime?
I guess the document ought to say something about this, although it can
be inferred. In :use-accessors t mode, it calls the accessor, which
is a generic function, and if object has no method for that generic
function you get the usual method-not-found error, whatever that is
specified to be. In :use-accessors nil mode, it does whatever
slot-value does, presumably signals an error if there is no slot with
the specified name.
pg. 18-Does CALL-NEXT-METHOD do the same thing as the current
RUN-SUPER in PCL?
I can't figure out -precisely- what RUN-SUPER in PCL does, but yes
they are the same concept.
pg. 19-Why not have PRINT simply be a generic function?
You mean pg 20? I'd have to see a more specific proposal, but I
think as soon as you started to write one you'd realize why PRINT,
already defined by Common Lisp, isn't the function that you want
to make generic.
Also, why
not have EQUALP (and perhaps EQUAL, and EQL as well) be generic
functions? This would allow programmers to define their own
notions of equality for two instances, and could come in handy
when objects have circularity.
I think this is something we ought to think about, although one tends
to be discouraged by the fact that equality is one area of Common Lisp
that is particularly poorly thought-out. I don't think EQL should
be made generic, though, because of efficiency considerations, and
because that would only really make sense if we made + and = generic,
which is definitely beyond the scope of what we're trying to do
in this particular proposal.
Aren't keywords self evaluating?
If so, then why quote them in the examples?
It's a matter of programming style. The style that we at Symbolics
use (some of us, anyway) is not to rely on the self-evaluation of
keywords in syntactic positions that admit any form and just happen
to have a keyword in them. Thus if (defun foo (&key a b) ...),
we would write (foo :a ':blatz :b ':bar) because the first and
third arguments are syntactically keywords (even though any form
would work) while the second and fourth arguments are only
keywords by coincidence. We find this less confusing than trying
to bum out quote marks from every possible place where they aren't
needed.
pg. 26-Must a generic function be defined before
DEFINE-METHOD-COMBINATION is evaluated? Must all
the mentioned methods? Any of them?
This doesn't make sense, so we need to improve the document so
it doesn't lead to this confusion. Evaluating DEFINE-METHOD-COMBINATION
does not depend on any particular generic function or methods. The
dependency, if any, is in the other direction.
pg. 27-What are the internal arguments mentioned in
the paragraph after the CALL-COMPONENT-METHOD syntax
description?
It's highly implementation-dependent, and in some implementations there
might not even be any.
pg. 32-There is a typo at the top of the page. The
second instance of (PIE CINNAMON APPLE) should be
(PASTRY CINNAMON APPLE).
Oops. I wonder how that slipped by.
pg. 37-The default info. here is good, but should
be moved up to where the options are defined.
We thought it was a better structure for the document to keep the
rationale behind various decisions separate from the expository material
that just tells it how it is without discussing rejected alternatives.
If you have more comments on places where the document is confusing,
or suggestions for how to make it better, I'd certainly like to hear
them.
∂17-Oct-86 2146 Moon@STONY-BROOK.SCRC.Symbolics.COM Computing the class precedence list
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 17 Oct 86 21:45:31 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 136230; Fri 17-Oct-86 14:52:10 EDT
Date: Fri, 17 Oct 86 14:50 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Computing the class precedence list
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <861010-155100-124@Xerox>,
<861010155847.2.GREGOR@AVALON.XEROX-PARC>
Message-ID: <861017145051.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 10 Oct 86 15:51 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Another way of explaining class precedence list.
The class precedence list is a left to right, depth first linearization
of the transitive closure of inheritance from the local super classes of
a class. It satisfies three constraints:
Constraint-0) A class appears only once in the list
Constraint-1) A class always precedes in the list all its local super
classes
Constraint-2) The order of the local supers is preserved
Stating C1 and C2 slightly differently:
C-1-2) A class must follow any class it is a direct super of,
or any class it follows in a local-supers list.
This is the same as what we have now, right?
The class precedence can be constructed in three steps.
1) Walk the inheritance tree in left to right depth first order,
recording all super classes in the order visited.
2) Remove duplicates, preserving the last occurrence of any class.
(This can actually be combined with step 1 without extra consing.).
3) Traverse the resluting list from left to right. If for any class c1,
there is a class to its right that c1 should follow (by C-1-2), move c1
to the right of the rightmost such class.
If any class needs to be moved a second time, it means there is a loops
of constraints that cannot be satisfied.
Date: Fri, 10 Oct 86 15:58 PDT
From: Gregor.pa@Xerox.COM
This code implements a compute-class-precedence-list algorithm the many
and varied features of which Danny will describe in a separate message.
[code deleted]
I have to admire your efficient algorithm design. After I removed the
format statement and the misuse of nunion on shared data, your algorithm
was 2.6 times faster than mine and only consed 78% as much, on the C6
example. The ratios were 1.6 and 84% on another example.
The bad news is, your algorithm doesn't always return the right answer.
Here are two examples I found:
(DEFCLASS1 C1 ())
(DEFCLASS1 C2 ())
(DEFCLASS1 C3 ())
(DEFCLASS1 D4 (C3 C2))
(DEFCLASS1 D5 (C2))
(DEFCLASS1 D6 (C3 C2 D5 D4))
(compute-class-precedence-list 'D6) => (D6 D4 C3 D5 C2)
which is incorrect, violating the constraint that D5 should precede D4.
The correct action is to signal an error, because C2 (and C3) is
constrained to be both before and after D4.
(DEFCLASS1 E1 (C1))
(DEFCLASS1 E2 (C2))
(DEFCLASS1 E3 (C3))
(DEFCLASS1 E4 (E3 E2 E1))
(DEFCLASS1 E5 (C1 C2))
(DEFCLASS1 E6 (C2 C3))
(DEFCLASS1 E7 (E5 E6 E4))
(compute-class-precedence-list 'E7) => (E7 E5 E6 E4 E3 E2 C3 E1 C1 C2)
which is incorrect, violating the constraint that C2 should precede C3.
The correct answer is (E7 E5 E6 E4 E3 E2 E1 C1 C2 C3).
While checking this out I discovered a transcription error in the code
I mailed out on 7 Oct. In COMPOSE-FLAVOR-COMPONENTS, there should not
be a SETQ of SLOW to NIL at the top of the loop; this defeats the SETQ
of SLOW to T at the bottom of the loop. The SETQ should be before the
loop. This was an error in conversion from the real version of LOOP
to the stripped down Common Lisp version of LOOP.
∂17-Oct-86 2155 Moon@STONY-BROOK.SCRC.Symbolics.COM Clarification of declaration requested
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 17 Oct 86 21:55:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 136322; Fri 17-Oct-86 15:55:01 EDT
Date: Fri, 17 Oct 86 15:53 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Clarification of declaration requested
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861017155332.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
In trying to figure out an issue about defgeneric, I need to ask
for clarification of Common Lisp. Does
(defun foo (x)
(declare (single-float x))
...)
imply
(proclaim '(ftype (function (single-float) t) foo)) ?
I guess Gabriel would be the best one to answer this.
∂17-Oct-86 2157 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Anonymous Generic Function Proposal
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 17 Oct 86 21:56:58 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 136355; Fri 17-Oct-86 16:14:50 EDT
Date: Fri, 17 Oct 86 16:13 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Anonymous Generic Function Proposal
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <861017-103458-5895@Xerox>
Message-ID: <861017161335.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 17 Oct 86 10:34 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
If there isn't some real
basis in experience, I think it would be highly premature to cast
it in concrete in a standard.
I think the feature would be as useful as flet and labels, with which we
have had significant experience.
Danny, if you don't agree that this reasoning is fallacious, then let's
discuss it. I'm going to assume that you do agree, so I'll say no more
unless I hear from you.
∂17-Oct-86 2159 Moon@STONY-BROOK.SCRC.Symbolics.COM Summary of Object Standard Discussions
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 17 Oct 86 21:59:41 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 136383; Fri 17-Oct-86 16:33:18 EDT
Date: Fri, 17 Oct 86 16:31 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Summary of Object Standard Discussions
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <861009-154111-1088@Xerox>
Message-ID: <861017163159.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 09 Oct 86 15:40 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
....Moon said this in his message:
``If you make the generic function FOO f-unbound and then do a DEFMETHOD
or DEFGENERIC for FOO, you get a new generic-function object that
doesn't know about any of the methods for the old FOO. Those methods
are gone ... so the data structure would be inconsistent.... There
could be other inconsistencies too.''
If generic functions are first-class, and if we've decided that this
first-class object (which comprises the generic function along with the
methods on it) is stored in the function cell, then FMAKUNBOUNDing them
is what you do when your intention is to `get a new generic-function
object that doesn't know about any of the <old> methods.''
I think this means that Moon did not understand what we agreed to.
I don't think so. I'm trying to clarify imprecise language. Putting back
the sentence of mine that you excerpted:
Those methods
are gone (except in the PCL meta-object protocol class-direct-methods
would still know about those methods, so the data structure would be
inconsistent).
A
first-class generic function is the thing that you funcall to get the
generic behavior and that has the methods logically inside it. When you
drop the last pointer to the generic function object, the garbage
collector can grab it away.
Except in the PCL meta-object protocol the class would still refer to
the methods and the methods would still refer to the generic function
so the garbage collector can't grab anything away. This is the inconsistency
I'm trying to clarify.
The other thing that needs to be clarified is exactly when (in the
course of macroexpanding, compiling, and loading/evaluating a DEFMETHOD
form, and calling the resulting method function) the mapping from name
of generic function to generic-function object happens. Also exactly
when the mapping from name of class (in a specialized parameter) to
class object happens. If we're going to include undefining and
redefining of these name-to-object mappings in the language, rather than
treating them as write-once relations, we have to be more precise about
when the lookups in these mappings happen. This is probably not very
hard.
When you do n DEFMETHODs on FOO, the function
cell for FOO is the only thing that logically has a pointer to the generic
function associated with the name FOO. If FMAKUNBOUND does not flush every
old method, and data structures end up inconsistent, then there is a bug
in your implementation.
So what this really means is that the linkage from class to methods used in
PCL is a bug, and the meta-object protocol for the standard (which we have
not yet begun to discuss in any serious way) cannot have the same sort of
linkage? What do people think about this, especially in the context of
browsers?
∂17-Oct-86 2201 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Summary of Object Standard Discussions
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 17 Oct 86 22:01:17 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 136406; Fri 17-Oct-86 16:48:05 EDT
Date: Fri, 17 Oct 86 16:46 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Summary of Object Standard Discussions
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <861013-183034-1785@Xerox>
Message-ID: <861017164650.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 13 Oct 86 18:31 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
From: Moon
The proliferation of -setf functions (e.g. remove-method-setf)
is getting disturbing and maybe we need an explicit notion of the
generic function objects that do setfs.
Should we go back to
(defmethod (:setf foo) ...)
since qualifiers are not around the name.
[discussion of other issues deleted for now]
No, because the real point of defmethod-setf was to have two separate
lambda-lists. That way the system gets to decide how to glue the two
lambda-lists together, and it can be implementation-dependent and
dependent on whether there are optional/rest/key arguments. My guess
is the setf-lambda-list goes at the end if there are only required
arguments, but goes at the front if there are any optional/rest/key.
You didn't like my proposal that defmethod, when it saw its first
subform was a list, would change its syntax to have two lambda-lists, as
I recall. I'm certainly willing to propose that again if you want.
Nit: it should be SETF, not :SETF. There's no reason to introduce
a new symbol here.
But what might be three reasonable proposals for the problem of the
proliferation of -setf functions would be to keep defmethod-setf
and defgeneric-setf, for the sake of the two lambda-lists, but
do one of the following:
(1) Functions that take an argument that can be either a generic
function object or the name of a generic function (remove-method
and method-combination-type are examples) will accept a list
(SETF foo) as the name of the generic function that gets defined
when you do (DEFGENERIC-SETF foo ...).
or
(2) A new function is introduced that translates from a generic
function object or its name to another generic function object,
the -setf one.
or
(3) Common Lisp is extended to expose the primitives underlying
DEFSETF, one of which is essentially the function proposed in (2).
∂19-Oct-86 1632 Masinter.pa@Xerox.COM Re: Summary of Object Standard Discussions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 19 Oct 86 16:32:46 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 19 OCT 86 16:32:50 PDT
Date: 19 Oct 86 08:20 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Summary of Object Standard Discussions
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 17 Oct 86 16:46 EDT
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861019-163250-1023@Xerox>
defmethod-setf would be easier to explain if there were a defun-setf
which defined a setf function.
∂20-Oct-86 0805 Bobrow.pa@Xerox.COM Re: "Classes" Document and Agreements Summary
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 20 Oct 86 08:05:14 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 20 OCT 86 08:01:19 PDT
Date: 20 Oct 86 08:01 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: "Classes" Document and Agreements Summary
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 17 Oct 86 17:45 EDT
To: common-lisp-object-system@sail.stanford.edu
cc: kempf%hplabsc@hplabs.HP.COM, snyder%hplabsc@hplabs.HP.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861020-080119-1375@Xerox>
This is an abbreviated response to the Kemp-Moon exchange, deleting the
parts I have nothing to say about.
pg. 5-:CLASS option-Is this for class slots? If so, it
seems to be a retraction of some earlier discussion about doing
this in the metaclass.
We need either to resolve the unclarities in the :ALLOCATION
slot option or to remove that option from the standard for the time
being; implementations can always add it as an extension for
experimentation purposes.
My understanding of our agreement, and at least the CommonLoops intent
is as follows. If the :class option is used for a slot, then the slot
is stored with the class. The implication of this is that all instances
share the same value. Determining whether a slot should be stored in an
instance or in its class is the responsibility of the class because the
ordinary user knows what semantics is wanted. The determination of how
instances themselves are represented (e.g. a list, block, with
indirection etc.) is the responsibility of the metaclass.
What about inheritance of class slots?
Are seperate copies of class state maintained in the super and
subclass objects or not?
Descriptions of class slots, just as despcriptions of other slots are
inherited unless overridden in a subclass. The state associated with a
class slot is stored only where it is explicitly specified in the class.
If a local description of a slot is provided, it completely overrides an
inherited description in a super class.
pg. 7-How is automatic updating of instances done when
it is redefined? Are there any hooks for user defined
transformation of instance state? For class state (re. :CLASS
option above)? Is there some way for a user to override this?
The working group hasn't discussed this yet, but we ought to.
One thing to look at (except for class variables) is the way
Flavors does it. There is a hook for user defined transformation.
Somewhere I have a collection of user comments on its deficiencies,
which we should look at.
The hook in CommonLoops for handling updating of obsolete instances is a
generic function that has as arguments the old (obsolete) instance, an
instance of the changed class, the old (obsolete) class and the new
(changed) class. The first two arguments allow users to write code
directly that updates the instances (the states of the two instances
will be switched at the end). The last two arguments allow
specialization depending on the meta-classes of the objects. I agree
that we should discuss this in more detail and look how Flavors does it.
Consider the case of developing extensions to a
programming environment while using the environment. One might
not want old instances of a redefined class to be updated, if
the behavior of the redefined class was not yet solid;
otherwise, the environment might break.
I think if you want to redefine a class without redefining it
you should give it a different name, perhaps using packages. In
Old Flavors we found lots of subtle reasons why just detaching the
old instances from the class structure and letting them continue to
use the old class doesn't really work (mainly having to do with
whether redefining a method should replace the old definition).
I agree with Moon.
And what if the parameter isn't of that class at runtime?
I guess the document ought to say something about this,
although it can be inferred. In :use-accessors t mode, it calls
the accessor, which is a generic function, and if object has no
method for that generic function you get the usual method-not-found
error, whatever that is specified to be. In :use-accessors nil
mode, it does whatever slot-value does, presumably signals an error
if there is no slot with the specified name.
I think if inference can't be done, then an explicit check ought to be
compiled into the code.
pg. 18-Does CALL-NEXT-METHOD do the same thing as the
current RUN-SUPER in PCL?
I can't figure out -precisely- what RUN-SUPER in PCL does, but
yes they are the same concept.
CALL-NEXT-METHOD is a generalization of RUN-SUPER that fits into the
declarative method-combination framework. RUN-SUPER in PCL is
implemented with a run-time search of the applicable methods. We
believe CALL-NEXT-METHOD can be implemented using method-combination
tecnology.
Thank you both for pushing the discussion forward.
∂20-Oct-86 0921 Bobrow.pa@Xerox.COM Re: Computing the class precedence list
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 20 Oct 86 09:21:48 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 20 OCT 86 09:21:13 PDT
Date: 20 Oct 86 09:21 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Computing the class precedence list
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 17 Oct 86 14:50 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861020-092113-1436@Xerox>
The class precedence list is a left to right, depth
first linearization of the transitive closure of inheritance
from the local super classes of a class. It satisfies three
constraints:
Constraint-0) A class appears only once in the list
Constraint-1) A class always precedes in the list all its local
super classes Constraint-2) The order of the local supers is
preserved
Stating C1 and C2 slightly differently:
C-1-2) A class must follow any class it is a direct super
of, or any class it follows in a local-supers list.
This is the same as what we have now, right?
Yes the constraints are meant to be the same.
The class precedence can be constructed in three steps.
1) Walk the inheritance tree in left to right depth
first order, recording all super classes in the order visited.
2) Remove duplicates, preserving the last occurrence
of any class. (This can actually be combined with step 1
without extra consing.).
3) Traverse the resluting list from left to right. If
for any class c1, there is a class to its right that c1 should
follow (by C-1-2), move c1 to the right of the rightmost such
class.
If any class needs to be moved a second time, it means
there is a loops of constraints that cannot be satisfied.
Your example works on the first example according to my description of
the algorithm.
(DEFCLASS1 C1 ())
(DEFCLASS1 C2 ())
(DEFCLASS1 C3 ())
(DEFCLASS1 D4 (C3 C2))
(DEFCLASS1 D5 (C2))
(DEFCLASS1 D6 (C3 C2 D5 D4))
Steps in this computation are
First compute left to right depth first up to joins (steps 1 and 2):
(D6 D5 D4 C3 C2) ;; and now start the fix ups.
--> ;check where the ↑ is shown
(↑ D6 D5 D4 C3 C2)
-->
(D6 ↑ D5 D4 C3 C2)
-->
(D6 ↑ D4 C3 C2 D5)
-->
(D6 ↑ C3 C2 D5 D4)
-->
(D6 ↑ C2 D5 D4 C3)
-->
(D6 ↑ D5 D4 C3 C2)
-->
Error: D5 needs to be moved again!!
If the code didn't work like this, we will fix it.
For the example:
(DEFCLASS1 E1 (C1))
(DEFCLASS1 E2 (C2))
(DEFCLASS1 E3 (C3))
(DEFCLASS1 E4 (E3 E2 E1))
(DEFCLASS1 E5 (C1 C2))
(DEFCLASS1 E6 (C2 C3))
(DEFCLASS1 E7 (E5 E6 E4))
Start with
(E7 E5 E6 E4 E3 C3 E2 C2 E1 C1)
-->
(↑ E7 E5 E6 E4 E3 C3 E2 C2 E1 C1)
-->
(E7 ↑ E5 E6 E4 E3 C3 E2 C2 E1 C1)
-->
(E7 E5 ↑ E6 E4 E3 C3 E2 C2 E1 C1)
-->
(E7 E5 E6 ↑ E4 E3 C3 E2 C2 E1 C1)
-->
(E7 E5 E6 E4 ↑ E3 C3 E2 C2 E1 C1)
-->
(E7 E5 E6 E4 E3 ↑ C3 E2 C2 E1 C1)
-->
(E7 E5 E6 E4 E3 ↑ E2 C2 C3 E1 C1)
-->
(E7 E5 E6 E4 E3 E2 ↑ C2 C3 E1 C1)
-->
(E7 E5 E6 E4 E3 E2 ↑ C3 E1 C1 C2)
UH OH!!!
C3 needs to be moved again impying an error.
The algorithm is too conservative.
This is because we have not computed the usually unneeded recursive
dependencies. The algorithm can be fixed.
One possible fix is to say:
"If any class needs to be moved a second time,there *MAY BE* a
loops of constraints that cannot be satisfied."
Either we can check for the error each time, or the list of dependencies
of the classes involved can be expanded recursively. Then these classes
will be moved far enough to the right on the next time they are moved.
In the usual case, (what I think is the usual case), this (MODIFIED)
algorithm should be faster.
An alternative fix is to check theposition of any class (in this case
C2) that causes a class (in this case C3) to move. In this case, C2
would be immediately moved past C1, and C3 past C2 after. There would
be no problem. We will send more code.
Did you actually run Gregor's code over all of the Flavors system to
find these bugs, or did you just think. If the former, are there any
cases actually in your system that the code does not work for?
-- danny
∂20-Oct-86 0928 Bobrow.pa@Xerox.COM Re: Summary of Object Standard Discussions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 20 Oct 86 09:28:34 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 20 OCT 86 09:28:46 PDT
Date: 20 Oct 86 09:28 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Summary of Object Standard Discussions
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 17 Oct 86 16:46 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861020-092846-1454@Xerox>
(1) Functions that take an argument that can be either a
generic function object or the name of a generic function
(remove-method and method-combination-type are examples) will
accept a list (SETF foo) as the name of the generic function that
gets defined when you do (DEFGENERIC-SETF foo ...).
or
(2) A new function is introduced that translates from a generic
function object or its name to another generic function object, the
-setf one.
or
(3) Common Lisp is extended to expose the primitives underlying
DEFSETF, one of which is essentially the function proposed in (2).
I am happy with 1, and like 3 as well. It seems that 2 without 3 is an
inappropriate extension. Let us push for 3 in the larger committee.
-- danny
∂20-Oct-86 1345 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Dispatching on optional/keyword arguments
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 20 Oct 86 13:45:19 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 138083; Mon 20-Oct-86 14:08:23 EDT
Date: Mon, 20 Oct 86 14:07 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Dispatching on optional/keyword arguments
To: Masinter.pa@XEROX.COM
cc: MMcM@STONY-BROOK.SCRC.Symbolics.COM,
Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <861017-163550-6338@Xerox>
Message-ID: <861020140752.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 17 Oct 86 16:35 PDT
From: Masinter.pa@Xerox.COM
Since I favor proposal 8, I checked your chart just for that column.
I think the answers are
yes yes yes no no yes yes no no no no no no 1 yes
Your chart gave
sort-of ? yes no yes yes no no no? no no yes no 1 yes
I guess you're working from a different version of that proposal
from the one that I saw in the mail, or what I interpreted of
what I saw in the mail. The one I'm working from is the one where
defmethod uses the same syntax as defun, but the methods selected
when an optional argument is specialized depend on whether the
optional argument was supplied or defaulted, even if the supplied
value is the same as the default value.
If we wanted to pursue this further we would need to have much more
precise specifications of each of the proposals. The purpose of
my message was to provide a general framework and summary of the
situation as currently understood, so I'm not surprised if it doesn't
contain all the details of every proposal that people have in mind.
∂20-Oct-86 1408 Bobrow.pa@Xerox.COM Re: Summary of Object Standard Discussions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 20 Oct 86 14:07:52 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 20 OCT 86 10:52:08 PDT
Date: 20 Oct 86 10:49 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Summary of Object Standard Discussions
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 17 Oct 86 16:31 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861020-105208-1536@Xerox>
Those methods are gone (except in the PCL meta-object
protocol class-direct-methods would still know about those
methods, so the data structure would be inconsistent).
A first-class generic function is the thing
that you funcall to get the generic behavior and that has the
methods logically inside it. When you drop the last pointer to
the generic function object, the garbage collector can grab it
away.
Except in the PCL meta-object protocol the class would still
refer to the methods and the methods would still refer to the
generic function so the garbage collector can't grab anything away.
This is the inconsistency I'm trying to clarify.
This is a general weakness of most garbage collectors. What we need in
Lisp is a combination of system pointers (not traced by the garbage
collector), and finalization on collection (so the system can get rid of
the system pointers). This does appear in the Cedar garbage collector.
Without something like that, then something like the PCL sticky
meta-object protocol will cause such potential garbage to stay around.
In my model of the world, this is not much stuff, so I am not worried
(should I be?).
The other thing that needs to be clarified is exactly when (in
the course of macroexpanding, compiling, and loading/evaluating a
DEFMETHOD form, and calling the resulting method function) the
mapping from name of generic function to generic-function object
happens. Also exactly when the mapping from name of class (in a
specialized parameter) to class object happens. If we're going to
include undefining and redefining of these name-to-object mappings
in the language, rather than treating them as write-once relations,
we have to be more precise about when the lookups in these mappings
happen. This is probably not very hard.
Yes we need to do this.
-- danny
∂20-Oct-86 1455 RPG Remarks on Generic Functions
To: common-lisp-object-system@SAIL.STANFORD.EDU
This long note contains some remarks addressed to the comments made
regarding generic functions. I think that people on this list do not share
the same ultimate view of what generic functions are and how they can be
used.
To me there are 3 things that the concept of generic functions buys us:
1. The ability to spread the definition of a generic function
among the places where the partial definitions make the most
sense. This is accomplished by placing DEFMETHODs in the
places where the relevant classes are defined, for example.
2. The ability to abstract the definition of a generic function
into parts (methods) that are conceptually independent. This
is accomplished by splitting the definition of a generic
function into independent parts where each part is the partial
function definition for a particular set of classes - each part
is a method. This leads to a new modularization technique.
3. The separation of the inheritance of behavior from placement of
code. Generic functions select methods based on the structure
of the class lattice, but the generic functions are not
constrained to be stored within that lattice.
Up until now I've seen a deep appreciation of only the first point by
members of this working group. I think this is natural because the only
experience that members of this working group have had is with
DEFMETHOD-like generic function definition.
Here is a summary of what I take to be our understanding of the nature of
generic functions.
There is a new type of first-class object, called a `generic function.'
It can be FUNCALLed and APPLYed exactly as Common Lisp functions can be.
When the function cell of a symbol contains a generic function, we say
that the symbol, call it S, `names' the generic function and that the
generic function is associated with the name, S. [This is exactly as
things are in Common Lisp with respect to functions.] Using MAKE-GENERIC
it is possible to create a generic function not associated with any
symbol.
Generic functions have internal structure. This internal structure
includes the argument list, the argument precedence order, method
combination information, and `methods.' Not required in that internal
structure is a `name' for the generic function. A generic function, in
some implementations, might have a name as part of itself but only as an
informational device for use by programming environment tools. The correct
functioning of generic function cannot depend on that name. When a
generic function is invoked, it invokes and combines some subset of the
methods. Which methods are invoked and how their results are combined
depends on the classes of the arguments supplied to the generic function
and on the method combination type of the generic function.
Methods are objects with, possibly, some internal structure - this has not
yet, I believe, been decided. Methods include a function, called the
`method function,' and possibly some other user-visible information. One
such possible part of the internal structure might be a pointer back to
the generic function of which the method is part. The term `method' is
commonly used to refer to method objects.
Methods are associated with generic functions, but are not associated
directly with any names except in an informational sense - the correct
functioning of a method cannot depend on its name. If a method is part of
a generic function which is associated with a symbol, S, we say that the
method is `defined for S.' ADD-METHOD and GET-METHOD add methods to and
retrieve method objects from, respectively, generic functions. DEFMETHOD
adds a method to the generic function associated with the symbol that is
the first argument of DEFMETHOD.
Methods are possibly applicable objects - I don't believe this has been
decided yet.
(typep <generic-function> 'function)
returns T, and possibly
(typep <method-object> 'function)
does too. It is certainly possible to write the following code:
(labels ((f (x) ...g...) ;calls g
(g (x) ...h...) ;calls h
(h (x) ...f...)) ;calls f
(add-method <gf> '((x c1)) #'f)
(add-method <gg> '((x c2)) #'g)
(add-method <gh> '((x c3)) #'h))
where <gf>, <gg>, and <gh> are generic functions. This defines
a set of methods whose method functions are mutually referential.
This does not imply that methods are directly invocable.
Generic functions are self-contained objects. The parts of generic
functions are not spread out in the heap, in tables, or in the class
lattice: The parts are contained in the generic function. Pointers to
generic functions might appear in various places for the proper function
of tools. One place is the class lattice, which defines the inheritance
structure on which the operation of generic functions depends. [Note:
an implementation is free to spread the definition wherever it likes
as long as it maintains the illusion of generic functions as first-class
objects.]
For example, environmental tools for associating methods with classes are
desirable. These tools will enable us to browse through a class lattice
and display all methods that operate on instances of the classes being
browsed. To do this, the tool must be able to determine for each class
the generic functions that operate on that class. In the case where a
generic function is associated with a symbol, it is nice to display that
symbol as the name of the generic function (that is, as the operator).
FMAKUNBOUND can disrupt the correct functioning of this tool.
FMAKUNBOUND, when applied to a symbol with which a generic function is
associated, removes the generic function definition from the function cell
of the symbol. FMAKUNBOUND cannot cause generic functions to behave
inconsistently with respect to their invocation semantics.
[(SETF (SYMBOL-FUNCTION ...) ...) also cannot disrupt invocation semantics.]
Let's look at an example. Suppose the user writes
(DEFMETHOD FOO ((X C)) ...)
The tool that displays generic functions for the class C will undoubtedly
display FOO by name. What does the class C store? It can store only the
symbol, FOO, or it can store not only the symbol, FOO, but also the
generic function stored in FOO's function cell. If the user does
(FMAKUNBOUND 'FOO) and the symbol alone is stored with the class, the tool
might display the wrong thing; if the user then does a second DEFMETHOD on
FOO, then the tool will very likely display the wrong thing. If the class
stores the symbol and the generic function, the tool can, after the
FMAKUNBOUND, display the anonymous generic function without the associated
name, FOO - assuming mutability of generic functions.
Possibly implementations that support tools like the one above will need a
function whose name could be REMOVE-GENERIC-FUNCTION-FROM-CLASS-LATTICE,
which removes from the class lattice all references to this generic
function. The primary client of this function will be the environment
tools.
Here is an example of some behavior I'd expect to see:
(DEFMETHOD FOO ((X C)) (FORMAT T "FOO, version 1, called on ~S~%" X))
<request to show the methods on C displays #<GENERIC-FUNCTION FOO>
and #<METHOD-OBJECT FOO> or something like that>
(FOO X) ;X an instance of C
causes
FOO, version 1, called on <X>
to be printed.
(SETQ BAZ #'FOO)
(FMAKUNBOUND 'FOO)
<request to show the methods on C displays #<GENERIC-FUNCTION 7128161>
and #<METHOD-OBJECT 86018603> or something like that>
(FOO X) ;X an instance of C
signals an error.
(DEFMETHOD FOO ((X C)) (FORMAT T "FOO, version 2, called on ~S~%" X))
<request to show the methods on C displays #<GENERIC-FUNCTION 7128161>
and #<METHOD-OBJECT 86018603> or something like that, and
#<GENERIC-FUNCTION FOO> and #<METHOD-OBJECT FOO> or something like that>
(FOO X) ;X an instance of C
causes
FOO, version 2, called on <X>
and nothing else, to be printed.
(FUNCALL BAZ X) ;same X
causes
FOO, version 1, called on <X>
(SETQ BAZ NIL)
results in a situation in which the tool displays things that might
confuse the user. At this point the user might like to clean up the
environment
Now let's turn our attention to naming. Suppose someone writes:
;;; Define a recursive generic function
(DEFMETHOD FOO ((X C))
;; Do something useful
(MUNCH X)
;; Do something related on a related class.
(FOO (SOME-OTHER-CLASS X)))
(SETF (SYMBOL-FUNCTION 'BAZ) #'FOO)
(DEFMETHOD FOO ((X C1)) ...)
Oh dear, (BAZ <c, an instance of C>) might lose because the recursive call
in FOO refers to some other generic function than the one supposedly
intended when the code for the first DEFMETHOD on FOO was written. Well,
we face the same problem with normal functions, and LABELS is used to
solve that:
(DEFUN FACT (N)
(LABELS ((FACT (N) (IF (ZEROP N) 1 (* N (FACT (1- N))))))
(FACT N)))
(FACT 47)
258623241511168180642964355153611979969197632389120000000000
(SETF (SYMBOL-FUNCTION 'BAZ) #'FACT)
(DEFUN FACT (X)
(FORMAT T "Adding ~S as a fact to the database!~% X)
(ADD-FACT X)
T)
(BAZ 47)
258623241511168180642964355153611979969197632389120000000000
We should be able to define generic functions and methods that have this
degree of insulation from the accidents of naming. Unless we define
something like GENERIC-FUNCTION-LABELS, the definition of such
self-contained generic functions will be ugly, containing FUNCALLs.
Some people have questioned whether it is a reasonable style to
write methods locally when it is clear that the intended purpose
of the standard is to let people write DEFMETHODs all over the place.
At the start of this message I mentioned several important things that
generic functions buy us. I will now paraphrase and expand on point number
2 above:
The concept of generic functions gives us the ability to
formulate the definition of a generic function as the
accumulation of methods, each modularly defined and each
specifically applicable to a set of classes. This enables the
programmer to formulate his code in natural pieces and to have
them assembled by the generic-function-calling mechanism.
The point behind my `lexically defined generic function' proposal is to
recognize and promulgate this programming methodology. If it is a good
methodology to define generic functions that are associated with symbols
using this modular approach, then it should be a good methodology to
define anonymous generic functions the same way. Using MAKE-GENERIC and
ADD-METHOD it is possible to do this, but at the expense of unreadable
code.
There is a second sort of `local' definition of methods that could make
sense - it is the one to which Gregor alluded in his message about my
anonymous generic function proposal. Suppose that a set of methods on the
symbol, FOO, has been defined. In a dynamic context the user might want
to temporarily extend FOO. I will use the name DFLET-METHOD; the user can
write:
(DFLET-METHOD ((FOO ((X C)) ...)) <form>)
and temporarily extend the generic function FOO to have this new method
associated with it during the execution of <form>. This, also, is a
reasonable programming methodology. I was curious about why Gregor thought
I meant something like DFLET-METHOD in my lexical generic function
proposal, even though I think my proposal was relatively clear on my
intention. I believe it is because Gregor thinks in terms of methods and
not in terms of generic functions. In this long message I have used the
term `generic function' relentlessly, and I have made the distinction
between generic functions and methods clear.
Moon raised the objection that because no one has experience with lexical
generic functions they should not be considered for inclusion as part
of the standard. People have had experience with DEFMETHOD, and people
have had experience with FLET/LABELS. Therefore the combination of them is
not a far-out concept. No one has had experience with meta-objects and
method combination in one system, so should we invoke Moon's design
principle to exclude from consideration a system that has both?
In writing a standard, one tries to take well-known programming language
constructs and methodology and from them make reasonable improvements and
meldings. Certainly when Common Lisp was being defined some risks were
taken in terms of adopting constructs that few people had experience with.
FLET/LABELS was familiar mostly to Steele and myself; the style of
multiple values adopted was sufficiently unlike others to be considered a
radical departure. The sequence functions were relatively unknown.
Let me relate the tale of TEX. Don Knuth designed TEX in 1977, and TEX78
contained one or two very powerful ideas for typesetting. The power of
these ideas captured the attention of people who care about typesetting
and beautiful manuscripts, to the extent that these people made a major
effort to convert their old documents to TEX.
Over a period of 4 years TEX was in heavy use, and people found that some
of the things they wanted to do were nearly impossible; people also found
that there were various TEX parameters that they wanted to control in
their macros. As with most non-Lisp-like languages, the macro facilities
were horrible.
Because Knuth adopted the design principle of retaining the existing
structure of TEX78 while taking strong consideration of the comments of
his loyal users, he decided to simply re-write TEX *adding* every facility
that was requested. There were approximately 200 of these facilities
added. Rather than sitting back and thinking about what these critiques
meant - all suggestions for improvements are really critiques - and
re-designing TEX, he just added them to TEX with minimal structural
changes. In fact, the structural changes were mostly those needed to
accomodate the facilities the users requested.
When I hear people state that the overriding design consideration for the
object system is the needs that existing users express or that it is
important to retain a familiar structure while adding a few new facilities,
I am reminded of TEX84, the worst (but most powerful) typesetting language
in existence by far. Yes, we should keep the past firmly in mind, but
not blindly in mind.
∂20-Oct-86 1522 RPG Re: Summary of Object Standard Discussions
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Someone writes:
The other thing that needs to be clarified is exactly when (in
the course of macroexpanding, compiling, and loading/evaluating a
DEFMETHOD form, and calling the resulting method function) the
mapping from name of generic function to generic-function object
happens. Also exactly when the mapping from name of class (in a
specialized parameter) to class object happens. If we're going to
include undefining and redefining of these name-to-object mappings
in the language, rather than treating them as write-once relations,
we have to be more precise about when the lookups in these mappings
happen. This is probably not very hard.
The mapping from generic function name to generic-function object
happens precisely at the same time that the mapping from function name
to function object happens in Common Lisp. Presumably DEFMETHOD acts like
DEFUN in its timing behavior. DEFMETHOD, I guess, acts like this:
(let ((gf (symbol-function <the symbol in question>)))
(unless (generic-function-p gf)
(setf (symbol-function <the symbol in question>)
(make-generic ...)))
(add-method gf <a right thing> <another right thing>)
<the symbol in question>)
This answer to the `mapping time' question reveals one of the beauties
of making generic functions first-class objects which are also functions:
The user does not need to learn anything new about how to treat calling
generic functions - they act exactly like Common Lisp functions.
The quote above includes the following:
...calling the resulting method function...
I don't believe our agreed-upon specification mentions whether it is
possible to directly call a method function except by having a pointer to
it before it became incorporated into a generic function.
;;; Define a function
(flet ((foo (x) ...))
;; make it a method for gf
(add-method gf '((x c)) #'foo)
;; call the method function just added
(foo <instance of c>)
;; call the generic function, gf, which causes the
;; method function just added to be called
(gf <instance of c>)
We have not decided whether
(funcall (get-method ...) ...)
is valid.
I'll let the rest of you discuss the class-name to class-object mapping
question.
By the way, the `tools' problem I mention in the long `remarks' message
and the problem of the system retaining `stale' pointers to generic
functions can both be solved by weak pointers, as Danny mentions. I think
there is no particular problem with weak pointers for stock hardware.
-rpg-
∂20-Oct-86 1759 Bobrow.pa@Xerox.COM Re: Method combination -- writeup for revised syntax
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 20 Oct 86 17:59:38 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 20 OCT 86 17:13:20 PDT
Date: 20 Oct 86 17:11 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Method combination -- writeup for revised syntax
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 15 Oct 86 23:39 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861020-171320-1149@Xerox>
Mostly I agree with the description provided of the CONTEXT so I will
only comment on small pieces.
To compare the precedence of two methods, examine their
parameter specializers in order from left to right.
This needs to be modified to take into account
:argument-precedence-order.
How about:
To compare the precedence of two methods, examine their
parameter specializers in order specified by their generic
function. This is by default, left to right.
Also, I don't like the term "parameter specializers". After your
description of how to extend the implementation of method selection to
all types, I think I would almost be happy going back to calling these
things "type-specifiers".
------
Method-combination -- Details
Rationale:
I would like the facilities used in define-method-combination to be
the same as those used by people using the meta-object protocol.
Hence, I want a more imperative format. However, I do like to supress
details from that users need not see.
I also would rather have one simpler version of
define-method-combination. Here is my next attempt, taking into account
your set of suggestions.
(DEFINE-METHOD-COMBINATION name ({method-option-keyword argument}*)
{form}+)
method-option-keywords include
:DESCRIPTION format-string
:DOCUMENTATION doc-string
:QUALIFIER-SET ({qualifier}*)
a list of qualifiers such that at least one must appear in every
non-null qualifier set. This is my solution to your checking problem.
It causes an error to be signalled for a method that does not satisfy.
NOTE: I have purposely omitted the lambda-list since the only place
where I saw it used was to allow a parameterized ordering, and thw added
complication did not seem worth it. If it is, then perhaps it can be
put in the options.
---
The form argument can involve the following primitives, most of which
are the same as those documented in your message. Those I only mention
without comment, I am implicitly agreeing with. Selecting methods is
described below.
MAKE-METHOD-CALL method-list &key :operator :around
It is fine with me to combine MAKE-METHOD-CALL to take an around
argument.
I think it is fine for make-method-call to take just a method object
instead of a list of one element
MAKE-METHOD-FROM-FORM form
METHOD-QUALIFIERS method
METHOD-COMBINATION-ERROR format-string &rest args
WRAP-AROUND-METHODS around-methods form
** Selecting Methods**
Methods are selected from the generic function from those applicable
using these forms. This allows the user to define their own bindings if
that is a preferred style, or to put them in-line. I propose two
primitives FIND-METHODS and SORT-METHODS. Both seem to be required in
the general case.
The version that has the mimimum number of arguments is
(FIND-METHODS &optional filter)
returns a list of args satisfying the simple filter
Then one uses:
(SORT-METHODS order method-list)
where order is one of :MOST-SPECIFIC-FIRST or :MOST-SPECIFIC-LAST
SORT-METHODS could allow merging
(SORT-METHODS order method-list-1 &rest method-lists)
It may be better for coding simple cases to extend FIND-METHODS.
(FIND-METHODS &optional filter order)
and not require a SORT-METHODS in most cases.
I think it would be useful to allow the filter to be written in a simple
boolean language with special forms:
(filter-and {qualifier-form}+)
(filter-or {qualifier-form}+)
(filter-not qualifier-form)
(filter-test <function>) ; applies to the method-qualifier list
({non-key-atoms}) ; Any list of atoms not starting with
; one of the four reserved words
; filter-and filter-or filter-not filter-test.
; As usual * matches anything.
atom ; same as (atom)
I am not attached to the details of this pattern language.
*****
Additional Keywords
:INCLUDE-DEFAULT-METHODS boolean
I argue against this on grounds that one should be explicit in labelling
methods.
:SELECT one of :FIRST, :LAST, :EVERY, or :REMOVE-DUPLICATES
Why shouldn't this be done in Lisp.
:ARGLIST list of forms
Is this important? I can't really evaluate this.
*****
To summarize where I stand today on the issues at the end of your last
message:
(1) Should there be a declarative thing that binds variables to
lists of methods, or should that be done imperatively? (Moon's
message lists some problems with the imperative approach).
No since I believe the problems you mention can be taken care of by a a
method-combination-option
(2) Can the method-selections and the forms be combined into a
template (built up from macros?) that puts the method-selections
right where the method-calls will go in the result?
Sure; we could use
(CALL-ALL-METHODS filter order operator around)
with the obvious interpretation (loosely speaking)
(MAKE-METHOD-CALL (FIND-METHODS filter order) operator around)
It is OK with me if we make CALL-ALL-METHODS have keyword syntax; I have
no religious beliefs on this subject.
(3) Naming and syntax of functions such as make-method-call.
I am reasonably happy with your name and description.
(4) "OR" qualifier-patterns.
Uses a filter-pattern language.
*****
Examples:
(define-method-combination :around+daemon
(:description "Default combination")
(wrap-around-methods (find-methods (:around))
`(multiple-value-prog2
,(call-all-methods :before)
,(make-method-call :around t
(or (find-methods)
(method-combination-error "A primary method is required.")
)
,(call-all-methods :after :most-specific-last))))
(define-method-combination :and (:description "and combination)
(call-all-methods (filter-or (:and) nil) :most-specific-first 'and)
∂20-Oct-86 1923 Moon@STONY-BROOK.SCRC.Symbolics.COM Instance transformation protocol proposal
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 20 Oct 86 19:22:11 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 138575; Mon 20-Oct-86 22:20:53 EDT
Date: Mon, 20 Oct 86 22:20 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Instance transformation protocol proposal
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <861020-080119-1375@Xerox>
Message-ID: <861020222040.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 20 Oct 86 08:01 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
[Kempf]
pg. 7-How is automatic updating of instances done when
it is redefined? Are there any hooks for user defined
transformation of instance state? For class state (re. :CLASS
option above)? Is there some way for a user to override this?
I don't know about CommonLoops, but in Flavors the same interface is used for
both ways that an instance can be transformed: (1) Redoing a DEFFLAVOR (aka
DEFCLASS) with different attributes such that the stored representation of
instances is changed; (2) CHANGE-INSTANCE-FLAVOR (aka CHANGE-CLASS). I'll
assume we're talking about both of these.
An apparently separate issue is whether the user has a hook invoked when
class variables are added or deleted. The easiest way to do this would be
as a metaclass method? I'm going to ignore this for now.
The hook in CommonLoops for handling updating of obsolete instances is a
generic function that has as arguments the old (obsolete) instance, an
instance of the changed class, the old (obsolete) class and the new
(changed) class. The first two arguments allow users to write code
directly that updates the instances (the states of the two instances
will be switched at the end). The last two arguments allow
specialization depending on the meta-classes of the objects. I agree
that we should discuss this in more detail and look how Flavors does it.
This assumes that the old and new instance are distinct objects. In some
implementations the instance can be updated in place, which gives better
performance by not messing up data structure locality. More importantly, I
don't see how slot accessors can be applied to the old instance, since any
attempt to access it is supposed to update it, in case (1) above. Also, I'm
not sure what you mean by "the states of the two instances will be switched at
the end."
To try to answer these questions, I went to the PCL source, but the version on
parcvax:/pub/pcl/class-prot.l doesn't seem to work anything like the way you
describe (perhaps it's an old version). It wasn't obvious which generic
function associated with change-class is the one that the user is supposed to
specialize with her own methods. Anyway, as far as I can tell the slot
contents of the old instance are passed around in the form of a property list
and there isn't an "old instance" object.
Right now Flavors provides a minimal interface; methods for the generic
function flavor:transform-instance receive only the instance as their
argument. Slots with the same name in the new and old flavors retain their
contents; other slots of the new flavor are initialized to their default
values, if any. If a slot is deleted the method has no way to find out what
its value used to be. User suggestions that I have recorded:
(a) Pass the old slots' values to the method as &key arguments.
(b) Pass an alist or property list of slot names and values to the method;
this could either be all of the old slots, or just the deleted slots. The
latter would be more efficient but would require something like
(getf deleted-slots slot-name (slot-value instance slot-name))
to get the old value of a slot.
(c) Pass a list of names of newly-introduced slots to the method.
(d) Allow the default value for newly-introduced slots of old instances
to be different from the default value for freshly-created instances.
(e) Pass the old and new flavor objects as arguments to the methods.
Similarities to the PCL implementation are evident.
My comments on the above suggestions:
(a) Bad idea, it uses up all the argument positions in the argument list.
(b) Pass a property list of just the deleted slots.
(c) Provide a function to compute this from (e).
(d) This can be simulated, using (c), by writing a method, except for
preventing the normal default value form from being evaluated. Unless
we can think of a non-complicated way for the user to exert closer
control, simulating it is probably good enough.
(e) Good idea.
THUS I PROPOSE:
(defgeneric transform-instance
(instance ;already transformed to new class
deleted-slots ;plist of slot names and values
new-class
old-class))
(defun new-slot-names (new-class old-class)
(set-difference (class-slot-names new-class) (class-slot-names old-class)))
When a method for transform-instance receives control, all system actions for
transforming the instance have already taken place. This is necessary to
avoid infinite recursion when applying slot accessors to the instance.
Transform-instance is only called if there are applicable methods
(equivalently, there is a default method that does nothing).
When a slot with no value is deleted, its entry in deleted-slots has nil as
the value.
∂21-Oct-86 0703 DLW@ALDERAAN.SCRC.Symbolics.COM Instance transformation protocol proposal
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 21 Oct 86 07:02:57 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 12850; Tue 21-Oct-86 10:01:49 EDT
Date: Tue, 21 Oct 86 10:08 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Instance transformation protocol proposal
To: Moon@STONY-BROOK.SCRC.Symbolics.COM,
common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <861020222040.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <861021100835.6.DLW@CHICOPEE.SCRC.Symbolics.COM>
Date: Mon, 20 Oct 86 22:20 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
This assumes that the old and new instance are distinct objects. In some
implementations the instance can be updated in place, which gives better
performance by not messing up data structure locality.
If by "locality" you mean "locality of reference" in the sense of demand
paging, I don't think this is the real issue. Much more important is
the semantic issue. When you change the class definition, and you have
in your Lisp world a bunch of existing data structure, you'd like all of
the instances contained in that structure to automatically behave in
accordance with the new class definition. This is valuable for
incremental program development. Old flavors could not do this, and we
received complaints from many quarters about the lack. I know you know
this but I wanted to make sure that the point was made explicit in this
discussion.
∂21-Oct-86 0711 RPG Re: Remarks on Generic Functions
∂20-Oct-86 1923 Masinter.pa@Xerox.COM Re: Remarks on Generic Functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 20 Oct 86 19:20:23 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 20 OCT 86 18:29:21 PDT
Date: 20 Oct 86 18:28 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Remarks on Generic Functions
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 20 Oct 86
14:55 PDT
To: RPG@SAIL.STANFORD.EDU
cc: masinter.pa@Xerox.COM
Message-ID: <861020-182921-1269@Xerox>
I think your message did well at explaining the role of generic
functions for purposes other than program modularity.
I think the arguments against including it in the standard at this time
rest more the belief that, while this is probably a reasonable
extension, there is no reason it couldn't be simply added in later. (It
is not possible, for example, to add "meta-objects" later to an
implementation that didn't use them.)
Do you believe there anything intrinsic about a GENERIC-FUNCTION-LABELS
that would prevent it from being added later?
If so, this should in itself give us pause, as we've not alloted a lot
of time for serious implementation design work.
If not, then we can happily defer this important capability to a later
deliberation, with the comfort that we will not be caught in a "TeX84"
situation.
Masinter.pa@xerox/su
Re: Remarks on Generic Functions
Larry, something like GENERIC-FUNCTION-LABELS could be added later.
Perhaps that would be a good idea, because the syntax possibilities are
not totally satisfying. However, I'm interested in pressing the argument
in order to press an examination of the ramifications of the idea on the
nature of generic functions. That is, I think that the funny syntaxes I
proposed are the best available, and the funniness of them, plus the
behavior of the resulting lexical generic functions, might point to
weaknesses with the concept of generic functions, which we need to explore
now.
Similarly, the pieces of code I sent in which methods are made out of
existing complexes of LABELS-defined functions points out some funny
corners. Even if we don't include lexical generic functions, these
problems should be explored to some depth.
One other solution I've looked at, but not proposed, is an extension to
Common Lisp itself, which is:
(function-let ((f (make-generic)))...)
which lets people bind lexical variables to things that must evaluate to
functions and to then use them as operators:
(function-let ((f (car l))
(g (aref foo 7 8)))
(+ (f 1 2) (g 3 4)))
This is a useful construct for Common Lisp even without Commonloops.
With it we can simply use ADD-METHOD to extend the generic function
and to name the generic functions reasonably.
-rpg-
∂21-Oct-86 0928 kempf%hplabsc@hplabs.HP.COM Re: Remarks on Generic Functions
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 21 Oct 86 09:28:29 PDT
Received: from hplabsc by hplabs.HP.COM ; Tue, 21 Oct 86 09:27:31 pdt
Received: by hplabsc ; Tue, 21 Oct 86 09:27:26 pdt
Date: Tue, 21 Oct 86 09:27:26 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8610211627.AA23114@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Remarks on Generic Functions
RPG's note on generic functions seems to clarify the proposal for
anonomyous generic functions. However, there seemed to be two
contradictory lines of thinking with regard to the relationship
between methods (particularly *multi*methods) and classes.
Under the 3 advantages of generic functions was listed:
> 3. The separation of the inheritance of behavior from placement of
> code. Generic functions select methods based on the structure
> of the class lattice, but the generic functions are not
> constrained to be stored within that lattice.
However, later on in the note when the relationship between generic
function objects and names is being clarified, the following example
is presented:
>The tool that displays generic functions for the class C will undoubtedly
>display FOO by name. What does the class C store? It can store only the
>symbol, FOO, or it can store not only the symbol, FOO, but also the
>generic function stored in FOO's function cell. If the user does
>(FMAKUNBOUND 'FOO) and the symbol alone is stored with the class, the tool
>might display the wrong thing; if the user then does a second DEFMETHOD on
>FOO, then the tool will very likely display the wrong thing. If the class
>stores the symbol and the generic function, the tool can, after the
>FMAKUNBOUND, display the anonymous generic function without the associated
>name, FOO - assuming mutability of generic functions.
In fact, with multimethods, the association is not between a class and
a generic function but rather between the typed lambda list and the
generic function. That is, it would be possible to have two methods
defined as:
(DEFMETHOD FOO ((X C1) (Y C2))
<code to do FOO>
)
(DEFMETHOD FOO ((X C1) (Y C3))
<code to do FOO>
)
and in neither case could one say that the method was associated with
a particular class, as would be the case with classical methods.
The implications of this need some thought. In particular, the idea
of operation inheritence, as it is "traditionally" seen in object
oriented systems, can no longer, I think, be relied upon to structure
tools, etc. which deal with generic functions and multimethods.
The lack of a distinguished argument provides no "hook" through which
operation inheritence can work.
A notion from algebraic typing theory which may be of interest in
this regard is "type conformity", which is used in some of the
statically typed object oriented languages (Trellis/Owl, Emerald).
Without specifying the exact algorithm, a class C conforms to
another class D if C provides at least the operations of D. In
addition, the results of C's operations must conform with those of
D, and the types of the arguments must conform in the opposite direction,
i.e., the arguments of D's operations must conform to those of C.
Since the current standard has no notion of a type (or class) signature,
in which a type declares it's abstract interface, it is not clear
how this notion could be formally fit into Classes.
Further modifications for Lisp (i.e., leaving out the typing of results)
would be needed; however, this is a pretty radical departure from
most existing notions of inheritence, and so would probably be best
left out of the standard. But it might be useful for structuring
thinking, particularly about tools which need to deal with multimethods
and classes.
As far as the rest of RPG's proposal goes, I think the justification
for anonomyous generics is now clearer. In particular, the (re)naming
semantics need further clarification, modulo Moon's comments, perhaps
the proposed local scoping constructs would help.
Jim Kempf kempf@hplabs
∂21-Oct-86 1049 Gregor.pa@Xerox.COM Instance transformation protocol proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Oct 86 10:49:07 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 21 OCT 86 10:33:23 PDT
Date: Tue, 21 Oct 86 10:32 PDT
From: Gregor.pa@Xerox.COM
Subject: Instance transformation protocol proposal
To: Moon@StonyBrook.SCRC.Symbolics.com
cc: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <861021103246.4.GREGOR@AVALON.isl.parc.xerox.com>
Line-fold: no
In CommonLoops, the same interface is used for both ways that an
instance can be transformed also.
In CommonLoops, the entrypoint function is change-class. It takes an
instance, and a class to change that instance's class to. Their is a
documented, internal function which takes the old instance and a new
"temporary instance" as arguments. The user can supply specific methods
for the internal function to convert instances from one class to
instances of another class.
For example:
(defclass point () ())
(defclass x-y-point (point) (x y))
(defclass rho-theta-point (point) (rho theta))
(defmethod change-class-internal ((x-y x-y-point) (r-t rho-theta-point))
(with-slots (x-y r-t)
(multiple-value-setq (rho theta) (convert-to-r-t x y))))
(defmethod change-class-internal ((r-t rho-theta-point) (x-y x-y-point))
(with-slots (x-y r-t)
(multiple-value-setq (x y) (convert-to-x-y rho theta))))
As Moon pointed out, the code in the version of PCL currently on vaxc
doesn't work this way. The correct code (which will soon be on vaxc) is:
(defmeth change-class ((object object) new-class)
(let ((old-class (class-of object)))
(let ((new-object (make new-class)))
(change-class-internal object new-object)
(setf (iwmc-class-class-wrapper object) (wrapper-of new-class)
(iwmc-class-static-slots object) (iwmc-class-static-slots new-object)
(iwmc-class-dynamic-slots object) (iwmc-class-dynamic-slots new-object))
object)))
(defmeth change-class-internal ((old object) (new object))
(let ((all-slots (all-slots old)))
(iterate ((name in all-slots by cddr)
(value in (cdr all-slots) by cddr))
(put-slot-always new name value))))
-------
∂21-Oct-86 1111 DLW@ALDERAAN.SCRC.Symbolics.COM Remarks on Generic Functions
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 21 Oct 86 11:11:02 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 12957; Tue 21-Oct-86 14:09:16 EDT
Date: Tue, 21 Oct 86 14:16 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Remarks on Generic Functions
To: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 20 Oct 86 17:55 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861021141601.3.DLW@CHICOPEE.SCRC.Symbolics.COM>
I read your long note. I don't disagree with anything in it. The
principles all make sense. My reservation about the lexical generic
function feature is only that I still have yet to see a realistic
example in which it's genuinely useful. This, by itself, still isn't
much of an objection. However, I'm afraid of getting a reaction from
the users and the other implementors, saying "this is all too big and
complicated, what's all this extraneous stuff for, don't these losers
have any appreciation for simplicity" and so on. I used to scoff at
that sort of complaint, but I've been getting more sensitive to it as
time goes on. These days I can often answer it with "Well, there were a
few users who really needed this ability, and the only way to make you
happy would be to make it so these users could not get their job done."
In this case, I don't think I'd be able to use that defense. The best
defense of the "extra" feature is symmetry and completeness. However,
if Common Lisp were fixed to be a lot more symmetrical and complete than
it is now, it would get significantly larger, and people already complain
that it's too large. I think this comes down to a question of engineering
judgement, and I don't think the answer is obvious.
∂21-Oct-86 1130 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Computing the class precedence list
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 21 Oct 86 11:30:01 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 139162; Tue 21-Oct-86 14:28:42 EDT
Date: Tue, 21 Oct 86 14:28 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Computing the class precedence list
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <861020-092113-1436@Xerox>
Message-ID: <861021142829.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 20 Oct 86 09:21 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
....
Did you actually run Gregor's code over all of the Flavors system to
find these bugs, or did you just think. If the former, are there any
cases actually in your system that the code does not work for?
I just thought. I can't easily run that code over all flavors defined in
my machine because the c-l-o-s ordering is weaker than Flavors ordering,
because you made us take out the :component-order option. Probably I can
figure out how to add that to your code, but it was too much for me the
other day. If you send me an algorithm that works on easy examples, I'll
see if I can work up the energy to run it over all flavors on my machine.
Stepping back a bit, I'm not sure why you're spending so much time and
energy trying to find a new algorithm to implement the constraint
satisfaction when there is already an algorithm that works. I'd rather
be spending my time on getting a draft document out by early December.
∂21-Oct-86 1220 RPG Re: Remarks on Generic Functions
∂21-Oct-86 1121 masinter.pa@Xerox.COM Re: Remarks on Generic Functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Oct 86 11:21:40 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 OCT 86 10:50:42 PDT
Date: 21 Oct 86 10:50 PDT
From: masinter.pa@Xerox.COM
Subject: Re: Remarks on Generic Functions
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 21 Oct 86
07:11 PDT
To: RPG@SAIL.STANFORD.EDU
cc: Masinter.pa@Xerox.COM
Message-ID: <861021-105042-1775@Xerox>
why not rename your proposed "GENERIC-FUNCTION-LABELS" to be "LABELS"?
(Its upward compatible, no?)
masinter.pa@xerox/su
``GENERIC-FUNCTION-LABELS'' => ``LABELS''
The second syntax is compatible. The second syntax is probably easier
to read than the first.
-rpg-
∂21-Oct-86 1320 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Summary of Object Standard Discussions
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 21 Oct 86 13:19:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 139282; Tue 21-Oct-86 16:11:35 EDT
Date: Tue, 21 Oct 86 16:11 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Summary of Object Standard Discussions
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <861020-092846-1454@Xerox>
Message-ID: <861021161112.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 20 Oct 86 09:28 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
(1) Functions that take an argument that can be either a
generic function object or the name of a generic function
(remove-method and method-combination-type are examples) will
accept a list (SETF foo) as the name of the generic function that
gets defined when you do (DEFGENERIC-SETF foo ...).
or
(2) A new function is introduced that translates from a generic
function object or its name to another generic function object, the
-setf one.
or
(3) Common Lisp is extended to expose the primitives underlying
DEFSETF, one of which is essentially the function proposed in (2).
I am happy with 1, and like 3 as well. It seems that 2 without 3 is an
inappropriate extension. Let us push for 3 in the larger committee.
OK, let's go with with (1) in the document. This affects all functions
that accept either a generic function object or the name of a generic
function as an argument. We can make a note to suggest someone look
into (3) separately.
∂21-Oct-86 1601 Bobrow.pa@Xerox.COM Re: Computing the class precedence list
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Oct 86 16:01:12 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 OCT 86 14:15:52 PDT
Date: 21 Oct 86 12:01 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Computing the class precedence list
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 21 Oct 86 14:28 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861021-141552-1089@Xerox>
Stepping back a bit, I'm not sure why you're spending so much
time and energy trying to find a new algorithm to implement the
constraint satisfaction when there is already an algorithm that
works. I'd rather be spending my time on getting a draft document
out by early December.
We are not spending much time, but I like having a single pass algorithm
I can understand, and explain. Onward and upward.
-- danny
∂21-Oct-86 1602 Bobrow.pa@Xerox.COM Re: Remarks on Generic Functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Oct 86 16:01:49 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 OCT 86 14:21:35 PDT
Date: 21 Oct 86 13:13 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Remarks on Generic Functions
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Tue,
21 Oct 86 09:27:26 pdt
To: kempf%hplabsc@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861021-142135-1106@Xerox>
The tool that displays generic functions for the class
C will undoubtedly display FOO by name. What does the class C
store? It can store only the symbol, FOO, or it can store not
only the symbol, FOO, but also the generic function stored in
FOO's function cell. If the user does (FMAKUNBOUND 'FOO) and
the symbol alone is stored with the class, the tool might
display the wrong thing; if the user then does a second
DEFMETHOD on FOO, then the tool will very likely display the
wrong thing. If the class stores the symbol and the generic
function, the tool can, after the FMAKUNBOUND, display the
anonymous generic function without the associated name, FOO -
assuming mutability of generic functions.
In fact, with multimethods, the association is not between a
class and a generic function but rather between the typed lambda
list and the generic function. That is, it would be possible to
have two methods defined as:
(DEFMETHOD FOO ((X C1) (Y C2)) <code to do FOO>
)
(DEFMETHOD FOO ((X C1) (Y C3)) <code to do FOO>
)
and in neither case could one say that the method was
associated with a particular class, as would be the case with
classical methods.
The implications of this need some thought. In particular, the
idea of operation inheritence, as it is "traditionally" seen in
object oriented systems, can no longer, I think, be relied upon to
structure tools, etc. which deal with generic functions and
multimethods. The lack of a distinguished argument provides no
"hook" through which operation inheritence can work.
With respect to multimethods, one way to think about signatures is as
follows. Every method takes a tuple of required arguments of some
specified type. If no type is specified, then that is equivalent to
specifying the type T. We can think of the tuple of k-types as defining
a type lattice or order k. The tuple <boat, position> is a 2-type.
We define k-type-1 to be a subtype of k-type-2 iff each of the elements
of the k-type-1 are a (not necessarily proper) subtype of the
corresponding element of k-type-2. Thus, <submarine,position> is a
subtype of <boat, position>, but <boat, position> and <submarine, T>
are incomparable.
Tools usually do not keep track of these tuple-types. They usually keep
track of classes, and each class participates in any number of such
types or the multimethods defined on those types. One would expect that
C1 would have associated with it (somehow) the two methods defined
above, for the types <C1 C2> and <C1 C3>. By associated here I mean
accessible and distinguishable say for a browser of classes.
In the environment we built for CommonLoops, asking a class for methods
associated with it produced a list of signatures that identified the
methods
e.g. ((FOO C1 C2) (FOO C1 C3) (BAR C1)(BAZ T C1) ...)
For methods of anonymous generic functions, one might expect signatures
such as
(#<generic 1261524> C1 C7>).
If the classes are to show only named generics, then only the names need
be stored, and the conversion to appropriate method signatures can be
done by search at request time. Anonymous generics would then not be
seen in the environment, thought they would still work.
∂21-Oct-86 1604 Gregor.pa@Xerox.COM Re: Summary of Object Standard Discussions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Oct 86 16:02:12 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 OCT 86 14:56:11 PDT
Date: 21 Oct 86 14:56 PDT
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Summary of Object Standard Discussions
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 21 Oct 86 16:11 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861021-145611-1163@Xerox>
I probably should have answered this before, sorry.
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Summary of Object Standard Discussions
(1) Functions that take an argument that can be either a
generic function object or the name of a generic function
(remove-method and method-combination-type are examples) will
accept a list (SETF foo) as the name of the generic function that
gets defined when you do (DEFGENERIC-SETF foo ...).
or
(2) A new function is introduced that translates from a generic
function object or its name to another generic function object, the
-setf one.
or
(3) Common Lisp is extended to expose the primitives underlying
DEFSETF, one of which is essentially the function proposed in (2).
I think we are going to have to have #2 in order for people to be able
to write many simple meta-object extensions. I think #1 is a nice
interface to this for some functions. I think Common Lisp should do #3,
as well as fix some of the existing bugs with setf.
So, for now I think we should do 1 and 2.
∂21-Oct-86 2302 DUSSUD%Jenner%ti-csl.csnet@CSNET-RELAY.ARPA Re: Summary of Object Standard Discussions
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 21 Oct 86 23:01:58 PDT
Received: from ti-csl by csnet-relay.csnet id ab09207; 21 Oct 86 18:21 EDT
Received: from Jenner (jenner.ARPA) by tilde id AA21829; Tue, 21 Oct 86 16:08:30 cdt
To: common-lisp-object-system%su-ai.arpa@csnet-relay.ARPA
Subject: Re: Summary of Object Standard Discussions
Date: 21-Oct-86 14:06:16
From: DUSSUD%Jenner@ti-csl.CSNET
Message-Id: <DUSSUD.2739294376@Jenner>
(1) Functions that take an argument that can be either a
generic function object or the name of a generic function
(remove-method and method-combination-type are examples) will
accept a list (SETF foo) as the name of the generic function that
gets defined when you do (DEFGENERIC-SETF foo ...).
or
(2) A new function is introduced that translates from a generic
function object or its name to another generic function object, the
-setf one.
or
(3) Common Lisp is extended to expose the primitives underlying
DEFSETF, one of which is essentially the function proposed in (2).
I think that 3 is not practical because setf forms are not always, or
required to be implemented using DEFSETF. Practically, it is not possible
to get "the" function responsible for implementing the SETF of a form unless
we have the whole setf expression.
Our context is more restrictive. Since we don't need the whole setf expression to figure out
what generic function to use, 2 makes sense.
I would vote for 1 or 2 and reject 3 (we would just ask for trouble pushing for 3).
Patrick.
∂22-Oct-86 1407 RPG DEF-GENERIC-OPTIONS
To: common-lisp-object-system@SAIL.STANFORD.EDU
My message - entitled ``Remarks on Generic Functions'' - points out the
primacy of generic functions in this standard. With that in mind, it is
time to discuss the nature of DEFGENERIC. Currently the description of
DEFGENERIC in the draft document reads:
The macro DEFGENERIC defines a generic function and stores it
in the symbol function cell of the symbol that is its name.
The new generic function object is returned as the result.
DEFGENERIC allows you to specify options and declarations that
pertain to the generic function as a whole.
The question is whether a DEFGENERIC form on a symbol must be evaluated
before any DEFMETHOD forms can be evaluated on that same symbol.
Here are some reasons why it ought to be required. I will follow that with
some reasons why it ought not be required.
1. Consider the case of anonymous generic functions. It makes no
sense to add methods to a generic function that does not exist.
Therefore, a generic function must be created with
MAKE-GENERIC (or with a GENERIC-FUNCTION-LABELS) before an
ADD-METHOD can be performed on it. Requiring the evaluation of
a DEFGENERIC form before the evaluation of any DEFMETHOD forms
creates a parallel situation between the symbol-based generic
function case and the anonymous generic function case.
2. A possible mental model for generic functions and methods is
that they are like structures and slots. It does not make
sense to create slots for a structure before a structure is
created - it is an absurdity. It makes sense to create the
values for those slots, but not the slots themselves.
Similarly, with anonymous generic functions it makes sense to
create the method functions before the generic function is
created, but evaluating the ADD-METHOD forms (or their
equivalent) must be done later.
3. Requiring the evaluation of a DEFGENERIC form before the
evaluation of any DEFMETHOD forms enforces a programming style
in which important objects - generic functions - are defined
before they are modified and used.
Here are reasons why evaluating a DEFGENERIC form before the evaluation of
any DEFMETHOD forms should not be required.
4. The effect of a series of DEFMETHOD forms followed by a
DEFGENERIC form is unambiguous. DEFGENERIC merely modifies some
of the options and declarations of the generic function, while
generic function creation is a separate event that happens when
the first DEFMETHOD form on a particular symbol is evaluated.
It is only the case of a DEFGENERIC form being evaluated on a
symbol for which there is no existing generic function that is
in question; in that case DEFGENERIC creates a generic function
first.
5. The programming style of spreading DEFMETHOD forms throughout
various file is encouraged. There is no requirement of loading
a `declarations' file full of DEFGENERIC forms. There are no
issues to decide regarding the re-loading of the declarartions
file.
6. The case of generic functions and methods is analogous to the
case of symbols: There is no requirement to define a symbol
before it can be used - simply mentioning the print name of a
new symbol will cause that symbol to be created and placed in an
appropriate package.
7. There is nothing to prevent programmers from using a more
modular style, putting all DEFGENERIC forms ahead of all
DEFMETHOD forms.
If we decide that 4 - 7 prevail, I suggest renaming DEFGENERIC, because
the primary function of DEFGENERIC is to specify options rather than
to define. I propose DEF-GENERIC-OPTIONS, and the first paragraph
of its specification should read:
The macro DEF-GENERIC-OPTIONS allows you to specify options and
declarations that pertain to a generic function as a whole. If
there is no generic function associated with the symbol
function cell of the symbol that is the name of the generic
function, a new generic function object is created and stored
in the symbol function cell. The generic function object is
returned as the result.
-rpg-
∂22-Oct-86 1513 Bobrow.pa@Xerox.COM Re: DEF-GENERIC-OPTIONS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Oct 86 15:11:17 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 OCT 86 14:27:54 PDT
Date: 22 Oct 86 14:28 PDT
Sender: Bobrow.pa@Xerox.COM
Subject: Re: DEF-GENERIC-OPTIONS
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 22 Oct 86
14:07 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861022-142754-2255@Xerox>
I believe that 4-7 should hold, and have no trouble with the name
DEF-GENERIC-OPTIONS (except to question the hyphenation -- is it
according to rules).
The macro DEF-GENERIC-OPTIONS allows you to specify options and
declarations that pertain to a generic function as a whole. If
there is no generic function associated with the symbol
function cell of the symbol that is the name of the generic
function, a new generic function object is created and stored
in the symbol function cell. The generic function object is
returned as the result.
The second paragraph should read:
The macro DEFMETHOD will expand into a call to
DEF-GENERIC-OPTIONS, with only the argument list filled in
(computed from the DEFMETHOD form). The rest of the options are
not specified. Evaluating DEF-GENERIC-OPTIONS several times is
allowed, provided specified information does not conflict with
previously stored information. If there is a conflict, an error
is signalled. Conflicts are:
1) changing the class of the generic-function causes an error
(inconsistent metaclasses).
2) the number of required arguments of the generic function is
changed.
3) other inconsistent changes in the argument list
Is this complete? correct?
-- danny
∂23-Oct-86 1835 Masinter.pa@Xerox.COM Re: Dispatching on optional/keyword arguments
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Oct 86 18:35:22 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 23 OCT 86 16:07:55 PDT
Date: 23 Oct 86 16:01 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Dispatching on optional/keyword arguments
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 20 Oct 86 14:07 EDT
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861023-160755-1667@Xerox>
I realize that I was thinking of a different proposal than the one you
had in mind for proposal 8. Call this proposal 9. (Do you think it is
the same as some of the others?)
The proposal I had in mind is as follows.
Methods can only discriminate on arguments that they require.
Discrimination happens only on arguments supplied, based on the method
signatures.
Different methods need not have conformal argument lists. If, using the
method signatures, a method is selected which requires more arguments
than are supplied, or which allows fewer arguments than are supplied, an
error is signalled. (The "argument signature" of the generic function
for a combination of methods is derived from the argument signatures of
the methods using a small algebra of argument signatures that I can
write up but for now leave unspecified. The space of argument signatures
includes a "no consistent set of arguments can be specified")
(This specification is not complete, but I hope I've described it well
enough to disambiguate it from other proposals for discriminating on
optionals.)
For example,
(defmethod foo ((a boat) &optional b) ..1..)
(defmethod foo ((a boat) (b number)) ..2..)
will get
..1.. with (foo (make-boat))
..2.. with (foo (make-boat) 3)
..1.. with (foo (make-boat) t)
adding
(defmethod foo ((a boat) (b integer) c) ..3..)
then
..2.. with (foo (make-boat) 3.0)
error with (foo (make-boat) 3)
∂23-Oct-86 1836 Masinter.pa@Xerox.COM :TYPE in DEFCLASS?
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Oct 86 18:36:02 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 23 OCT 86 18:21:35 PDT
Date: 23 Oct 86 18:15 PDT
From: Masinter.pa@Xerox.COM
Subject: :TYPE in DEFCLASS?
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <861023-182135-1785@Xerox>
This was probably just an oversight, but the current document leaves out
the :type slot option.
It may be that many implementations would just ignore the :type
slot-option, but leaving it out would make it harder to remove
defstruct.
∂23-Oct-86 2337 RPG Re: DEF-GENERIC-OPTIONS
∂23-Oct-86 1835 Masinter.pa@Xerox.COM Re: DEF-GENERIC-OPTIONS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Oct 86 18:34:58 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 23 OCT 86 15:51:44 PDT
Date: 23 Oct 86 15:45 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: DEF-GENERIC-OPTIONS
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 22 Oct 86
14:07 PDT
To: RPG@SAIL.STANFORD.EDU
cc: bobrow.pa@Xerox.COM, masinter.pa@Xerox.COM
Message-ID: <861023-155144-1650@Xerox>
Maybe this is beating a dead horse, so I won't send it out to the whole
list.
Your argument (1) "It makes no sense to add methods to a generic
function that does not exist. Therefore, a generic function must be
created with MAKE-GENERIC (or with a GENERIC-FUNCTION-LABELS) before an
ADD-METHOD can be performed on it."
is an argument for making generic functions immutable, and have
ADD-METHOD return a new generic function rather than modify the old.
Your argument (2) suggests that the mental model for generic functions
and methods as being like structures and slots is inappropriate. I
suggest a mental model of a property or association list, which can
intially start out empty and have elements attached to it.
Your argument (3) is a strong argument against requiring defgeneric,
since it states that we are enforcing a programming style, but this
style is inconsistent with the current programming style in Loops,
Flavors and Smalltalk and other object-oriented programming languages,
which do not require defining the (equivalent of) the generic function
before modifying it.
- - - - - -
In your writup of the spec, you don't say what happens if there IS a
generic function already exists for the symbol when DEF-GENERIC-OPTIONS
is called:
The macro DEF-GENERIC-OPTIONS allows you to specify options and
declarations that pertain to a generic function as a whole. If
there is no generic function associated with the symbol
function cell of the symbol that is the name of the generic
function, a new generic function object is created and stored
in the symbol function cell. The generic function object is
returned as the result.
/sub
masinter.pa@parc
DEF-GENERIC-OPTIONS
1. If ADD-METHOD creates new generic functions all the time (which means that
you cannot build tools to display methods associated with classes and keep
data structures consistent), does this mean that (MAKE-GENERIC) is defined
to be (ADD-METHOD () () ())? Or (ADD-METHOD)?
2. My (2) does not suggest that the structure/slot model is inappropriate,
you do. My (2) reminds you of your belief.
3. This is the only argument I'm willing to buy.
I thought my description of DEF-GENERIC-OPTIONS fairly clearly, but not
crystal clearly, hinted that DEF-GENERIC-OPTIONS mostly modifies an
existing generic function and that in special cases it creates a new one.
Danny is right in that inconsistencies specified by DEF-GENERIC-OPTIONS
or DEFMETHOD will signal errors.
I am actually somewhat neutral on whether DEFGENERIC should be required. I
would have liked to have seen a complete symmetry between
DEFGENERIC/DEFMETHOD and MAKE-GENERIC/ADD-METHOD, but I guess tradition
will win out over rationality. I also makes my `critique' paper easier
to write.
-rpg-
∂24-Oct-86 1321 Masinter.pa@Xerox.COM Re: Dispatching on optional/keyword arguments
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Oct 86 13:21:19 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 OCT 86 10:39:30 PDT
Date: 23 Oct 86 18:59 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Dispatching on optional/keyword arguments
In-reply-to: Masinter.pa's message of 23 Oct 86 16:01 PDT
To: Masinter.pa@Xerox.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861024-103930-1108@Xerox>
On review, I may have been describing your option (7), although I think
what threw me was "Can dispatch on optional arguments -- no"; it allows
dispatching on arguments that are optional in *other* methods, e.g.
(defmethod foo ((a boat) &optional b) ..1..)
(defmethod foo ((a boat) (b integer)) ..2..)
(foo (make-boat)) gets ..1..
(foo (make-boat) t) gets ..1..
(foo (make-boat) 3) gets ..2..
∂26-Oct-86 2029 Kahn.pa@Xerox.COM Re: Instance transformation protocol proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Oct 86 20:28:56 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 26 OCT 86 20:03:51 PST
Date: 26 Oct 86 20:03 PST
Sender: Kahn.pa@Xerox.COM
Subject: Re: Instance transformation protocol proposal
In-reply-to: Gregor.pa's message of Tue, 21 Oct 86 10:32 PDT
To: Gregor.pa@Xerox.COM
cc: Moon@StonyBrook.SCRC.Symbolics.com,
Common-Lisp-Object-System@Sail.Stanford.edu
From: Ken Kahn <Kahn.pa@Xerox.COM>
LineFold: No
Message-ID: <861026-200351-2549@Xerox>
I noticed you used multiple-value-setq inside a with-slots. As in:
(defmethod change-class-internal ((x-y x-y-point) (r-t rho-theta-point))
(with-slots (x-y r-t)
(multiple-value-setq (rho theta) (convert-to-r-t x y))))
I think that is perfectly reasonable but to be consistent shouldn't one add to
Common Lisp a multiple-value-setf? In other words, why should this work only
inside of a with-slots?
----- ken
∂26-Oct-86 2029 Kahn.pa@Xerox.COM Re: Remarks on Generic Functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Oct 86 20:29:10 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 26 OCT 86 20:22:05 PST
Date: 26 Oct 86 20:22 PST
Sender: Kahn.pa@Xerox.COM
Subject: Re: Remarks on Generic Functions
In-reply-to: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>'s
message of Tue, 21 Oct 86 14:16 EDT
To: DLW@ALDERAAN.SCRC.Symbolics.COM
cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
From: Ken Kahn <Kahn.pa@Xerox.COM>
Message-ID: <861026-202205-2557@Xerox>
The best defense of the "extra" feature is symmetry and
completeness. However, if Common Lisp were fixed to be a lot more
symmetrical and complete than it is now, it would get significantly
larger, and people already complain that it's too large.
I agree that Common Lisp would be larger but in some important sense it
would become simpler. If one didn't go along with Dick's proposal then
one has to explain generic functions by saying that they are like
functions except that you can't create them in ways analogous to LABELS,
FLET, etc.
In other words, the language becomes more complex because one needs to
remember exceptions.
----- ken
∂26-Oct-86 2029 Kahn.pa@Xerox.COM Re: Anonymous Generic Function Proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Oct 86 20:29:23 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 26 OCT 86 20:27:14 PST
Date: 26 Oct 86 20:27 PST
Sender: Kahn.pa@Xerox.COM
Subject: Re: Anonymous Generic Function Proposal
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 14 Oct 86
16:59 PDT
To: RPG@SAIL.STANFORD.EDU
CC: common-lisp-object-system@SAIL.STANFORD.EDU
From: Ken Kahn <Kahn.pa@Xerox.COM>
Message-ID: <861026-202714-2558@Xerox>
There is probably only one reasonable way to define anonymous
generic functions:
#'(generic-lambda <method-spec>*)
where <method-spec> is
(<qualified lambda list> . <body>)
I would like to see someplace to add generic function options to specify
the generic function class, method combination, argument precedence
lists, etc.
----- ken
∂26-Oct-86 2029 Kahn.pa@Xerox.COM Re: DEF-GENERIC-OPTIONS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Oct 86 20:29:03 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 26 OCT 86 20:08:15 PST
Date: 26 Oct 86 20:08 PST
Sender: Kahn.pa@Xerox.COM
Subject: Re: DEF-GENERIC-OPTIONS
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 22 Oct 86 14:28 PDT
To: Bobrow.pa@Xerox.COM
cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
From: Ken Kahn <Kahn.pa@Xerox.COM>
Message-ID: <861026-200815-2552@Xerox>
The macro DEFMETHOD will expand into a call to
DEF-GENERIC-OPTIONS, with only the argument list filled in
(computed from the DEFMETHOD form). The rest of the options are
not specified. Evaluating DEF-GENERIC-OPTIONS several times is
allowed, provided specified information does not conflict with
previously stored information. If there is a conflict, an error
is signalled. Conflicts are:
1) changing the class of the generic-function causes an error
(inconsistent metaclasses).
2) the number of required arguments of the generic function is
changed.
3) other inconsistent changes in the argument list
Is this complete? correct? -- danny
I think 1) is too strict. Just as there is (or at least was) a protocol
about compatible-metaclass-p in PCL there aught to be some such here.
One may, for example, change the class of the generic function to a
subclass with a little extra functionality. By the way didn't you mean
"inconsistent meta-objects"?
----- ken
∂27-Oct-86 1216 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 Oct 86 12:15:58 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 27 OCT 86 11:00:17 PST
Date: 27 Oct 86 10:59 PST
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Anonymous Generic Function Proposal
In-reply-to: Ken Kahn <Kahn.pa>'s message of 26 Oct 86 20:27 PST
To: Kahn.pa@Xerox.COM
cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861027-110017-3052@Xerox>
There is probably only one reasonable way to define
anonymous generic functions:
#'(generic-lambda <method-spec>*)
where <method-spec> is
(<qualified lambda list> . <body>)
I would like to see someplace to add generic function options
to specify the generic function class, method combination, argument
precedence lists, etc.
Clearly one could do
(let ((gf (make-instance <generic-function-class>)))
... stuff to set method combination, argument precedence lists,
etc
(add-method gf <method-spec1>) ...)
Syntactic sugar is useful for the most common cases, and the payoff for
adding syntax must be proved.
With this caveat, I would suggest the following possible syntax:
#'(generic-lambda {(:generic-options
<options-from-def-generic-options>)}
<method-spec>*)
-- danny
∂27-Oct-86 1415 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Instance transformation protocol proposal
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Oct 86 14:15:07 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 143724; Mon 27-Oct-86 17:14:52 EST
Date: Mon, 27 Oct 86 17:13 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Instance transformation protocol proposal
To: Ken Kahn <Kahn.pa@XEROX.COM>
cc: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <861026-200351-2549@Xerox>
Message-ID: <861027171337.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 26 Oct 86 20:03 PST
From: Ken Kahn <Kahn.pa@Xerox.COM>
I noticed you used multiple-value-setq inside a with-slots. As in:
(defmethod change-class-internal ((x-y x-y-point) (r-t rho-theta-point))
(with-slots (x-y r-t)
(multiple-value-setq (rho theta) (convert-to-r-t x y))))
I think that is perfectly reasonable but to be consistent shouldn't one add to
Common Lisp a multiple-value-setf? In other words, why should this work only
inside of a with-slots?
A proposed, but rejected, extension to Common Lisp was
(setf (values (point-rho p) (point-theta p))
(convert-to-r-t x y))
I forget why this was rejected. Probably the majority of the Common Lisp
committee couldn't see in 1983 any applications for it.
This seems like the appropriate syntax for such a feature, rather than
adding a new special form.
By the way it's trivial to implement, but not in a portable way. What I
mean is that it is trivial to add to most setf substrates.
∂27-Oct-86 1510 edsel!bhopal!jonl@navajo.stanford.edu Remarks on Generic Functions
Received: from NAVAJO.STANFORD.EDU by SAIL.STANFORD.EDU with TCP; 27 Oct 86 15:10:21 PST
Received: by navajo.stanford.edu; Mon, 27 Oct 86 15:08:43 PST
Received: from bhopal.edsel.uucp by edsel.uucp (2.2/SMI-2.0)
id AA01704; Sat, 25 Oct 86 01:02:16 pdt
Received: by bhopal.edsel.uucp (1.1/SMI-3.0DEV3)
id AA18072; Sat, 25 Oct 86 01:01:29 PDT
Date: Sat, 25 Oct 86 01:01:29 PDT
From: edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)
Message-Id: <8610250801.AA18072@bhopal.edsel.uucp>
To: navajo!RPG%SAIL.STANFORD.EDU@navajo.stanford.edu,
navajo!common-lisp-object-system%SAIL.STANFORD.EDU@navajo.stanford.edu
In-Reply-To: Daniel L. Weinreb's message of Tue, 21 Oct 86 14:16 EDT
Subject: Remarks on Generic Functions
Date: Fri, 24 Oct 86 23:51:53 PDT
From: jonl (Jon L White)
To: navajo!DLW%ALDERAAN.SCRC.Symbolics.COM
In-Reply-To: Daniel L. Weinreb's message of Tue, 21 Oct 86 14:16 EDT
Subject: Remarks on Generic Functions
I see two still-open issues about "lexical generics" in your note:
1) Does their addition to the language move it more towards the judgement
"this is all too big and complicated, what's all this extraneous stuff
for, don't these losers have any appreciation for simplicity" and so on.
2) Will there ever be any useful scenarios where they will be used. Who
will want to use them. Could they find another way to "do it" without
requiring "lexical generics" .
What seems obvious to some people, and not so obvious to others, is that
the language will be more complex **without** lexical generics than with
them. The reason is, quite simply, that once generic functions become
first-class in the way they have, then the more syntactic differences
there are between their usage and normal function usage, the more complex
it will be to understand them.
The "lexical" notion applies to the syntactical meaning of program
identifiers, rather than to any deep-seated meaning about the values
they identify. [What is surprising to me is why there aren't more people
clamoring down the Common Lisp door for "lexical defstructs"; there have
been some already, I know]. I think Gregor suggested a similar thing in
a note last week about how to implement "lexical generics" as syntactic sugar
on top of pre-existing "anonymous generic function" capability.
With regard to (2), I might say that the whole thrust of "lexicality" in
Common Lisp has not necessarily been a unanimous blessing. Sure, everyone
applauds the unification of the compiler and interpreter on the treatment
of local variables, but not everyone cares even on whit about FLET and
LABELS. One could argue that Lisp got along for 20 years without such
constructs and didn't need them (and may still doesn't?); on the other hand
even if one doesn't use them himself, he might recognize that it's a
programming style that's coming of age now, and not just in Lisp.
It would appear that "packages" in some strongly-typed languages are in fact
the means of achiving lexical modularity therein -- which may be why so
many Lisp users have been confused about the differences between local
variables and "packages" in Lisp [this isn't the place for extending the
"packages" discussion, but it certainly is a worthwile one]. Suffice it
to say that Lisp's unit of lexical modularity is something smaller than the
"module"; and that Lisp's introspective nature -- program is data, data
is program -- means that lexicality won't necessarily give 100% isolation.
By the way, I`m not one of the nay-sayers on lexicality (although I will
ocasionally rise to defend dynamic scoping -- Common Lisp is *both* lexically
scoped and dynamically scoped).
Let me take an example of one of the minor uses I've found for FLET over the
past year and extend it into the realm of generic functions; then let me ask
you if you don't agree that the similarity between them is very striking.
[actual examples changed for illustrative purposes].
;;minor modification of a pre-existing function, for local context:
(flet ((sqrt (x &optional tolerance)
(let ((sys::*sqrt-tolerance* (* .1 (or tolerance
sys::*sqrt-tolerance*))))
(sqrt x))))
. . .
;; here's a section with more critical accuracy needs
(setq y (sqrt x))
. . .
;; here's another section with more critical accuracy needs
(setq z (sqrt x .01))
. . .
)
Now, in place of SQRT, substitute PRINT, and in place of *SQRT-TOLERANCE*,
substitute *PRINT-STRUCTURE*; finally, consider the need to throw in
a "method" to this locally redefined PRINT that handles some instances
differently.
(gflet (((print (x &optional (stream *standard-output*))
;; default method just goes back to global print definition
(let ((*print-structure* nil))
(print x stream)))
(print ((x foo) &optional (stream *standard-output*))
;; 'foo' instances need more visibility
(let ((*print-structure* t))
(print x t)))))
. . .
(maybe-modify-generic-function #'print)
. . .
(print z)
. . .
)
Not only does lexicality shield the "(print z)" from using the global print,
but the call to 'maybe-modify-generic-function' is with a different object
than would be found in the symbol-function cell of PRINT. Even though there
may be side-effects upon the generic function, the lexical naming provides
a way of locally insulating these effects from the global environment.
Incidentally, it would appear as though defining GFLET by extending FLET
would work well enough, except that it forces the issue of modifying
existing systems even before the clos proposal becomes a standard. The
examples seem to say that the only difference between them is the extra
layer of parentheses; but if some other syntax is to be adopted, then I'm
sure that it too will differ just enough from current FLET so that the
use can unambiguously specify whether he means a generic lexical function,
or an ordinary lexical function.
-- JonL --
∂27-Oct-86 1920 Moon@STONY-BROOK.SCRC.Symbolics.COM Remarks on Generic Functions
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Oct 86 19:20:04 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 143925; Mon 27-Oct-86 21:26:37 EST
Date: Mon, 27 Oct 86 21:25 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Remarks on Generic Functions
To: common-lisp-object-system@SU-AI.ARPA
In-Reply-To: <8610250801.AA18072@bhopal.edsel.uucp>
Message-ID: <861027212521.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Sat, 25 Oct 86 01:01:29 PDT
From: edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)
....
Now, in place of SQRT, substitute PRINT, and in place of *SQRT-TOLERANCE*,
substitute *PRINT-STRUCTURE*; finally, consider the need to throw in
a "method" to this locally redefined PRINT that handles some instances
differently.
(gflet (((print (x &optional (stream *standard-output*))
;; default method just goes back to global print definition
(let ((*print-structure* nil))
(print x stream)))
(print ((x foo) &optional (stream *standard-output*))
;; 'foo' instances need more visibility
(let ((*print-structure* t))
(print x t)))))
(print z))
Not only does lexicality shield the "(print z)" from using the global print...
Yes, but what happens if Z is a list of FOOs? I don't think the print
method for LIST is going to call back to the version of the print generic
function that calls your special print method for FOO.
This is just poking nits in a specific example. However, I don't think
it's meaningless on that account. It's things like this that lead to my
claim that these ideas are not well thought out and will not be well
thought out until they have been used in real applications, and until
then it is inappropriate to standardize them. That's not to say there
is anything wrong with these ideas; I think that the same phenomenon
happens with all ideas.
Instead of standardizing these ideas, we should make sure that the
standard does not rule out the implementation of these ideas, and then
provide some implementations in an unstandardized way. Perhaps not
everyone agrees, but I feel that once you standardize something you are
committed not to change it in any big way, so it had better be right.
∂27-Oct-86 1936 LGD new files on [CLS,LSP]
To: common-lisp-object-system@SAIL.STANFORD.EDU
I have edited the files that Sonya placed out on CLS,LSP earlier today so
that they can be run through TEX and printed.
These files are working versions. While they can be run through TEX
they are not yet in TEX format.
The new files are functi.tex, functi.dvi, concep.tex, and concep.dvi.
Linda
∂27-Oct-86 2034 RPG Re: Remarks on Generic Functions
To: common-lisp-object-system@SAIL.STANFORD.EDU
Moon writes:
``Yes, but what happens if Z is a list of FOOs? I don't think the print
method for LIST is going to call back to the version of the print generic
function that calls your special print method for FOO.''
If PRINT calls itself recursively on the components of the list, then it
certainly will call the further-specialized version of PRINT that
specializes on FOOs. There are two possible points Moon can be making
here:
1. He might think that GFLET modifies a generic function
associated with a symbol by copying the contents of the
function cell, so that the system-supplied PRINT will call
itself (as if it were defined using LABELS rather than DEFUN)
directly rather than through the function cell. If this is
what he believes then he is stating merely that PRINT is a poor
example to use, because the user cannot specialize on it.
2. He might believe that PRINT is a poor function to use as an
example because it will call PRIN1 internally, and therefore
the user cannot specialize on PRINT to get the results he
expects.
In either event he is stating merely that PRINT is a poor example, because
one ought not to specialize on code whose internal structure is unknown
unless that code was written with specialization in mind. Let's use another
example:
(DEFMETHOD COUNT-CONSTITUENTS (L)
(COND ((NOT (CONSP L)) 1)
(T (+ (COUNT-CONSTITUENTS (CAR L))
(COUNT-CONSTITUENTS (CDR L))))))
(GLFET ((COUNT-CONSTITUENTS ((L BAZOLA))
(+ JILLION-SKILLION (MAP-BAZOLA #'COUNT-CONSTITUENTS BAZOLA))))
(COUNT-CONSTITUENTS <some interesting thing>))
This will do the expected thing. The recursive calls to
COUNT-CONSTITUENTS in the first DEFMETHOD will invoke the specialized
version of COUNT-CONSTITUENTS, precisely because those recursive calls
pass through the function cell of the symbol COUNT-CONSTITUENTS.
This all falls out of the description of generic functions in my
`remarks' message. If Moon doesn't think that the recursive call to
COUNT-CONSTITUENTS in the GFLET will call the global (function cell)
definition of COUNT-CONSTITUENTS, then he doesn't understand the concepts
in my message.
Perhaps it is best to wait until these ideas are put into use before
putting them in the standard, but we must take care to not accidentally
preclude them from being implemented because they violate something in the
specification. Therefore, we should, at least, be considering these
possible extensions.
Certainly it is not the case that we are restricted to some combination of
ideas already implemented for inclusion in the standard - we are allowed
to think about them and refine them first.
-rpg-
∂27-Oct-86 2151 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Remarks on Generic Functions
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Oct 86 21:51:27 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 143968; Tue 28-Oct-86 00:51:27 EST
Date: Tue, 28 Oct 86 00:50 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Remarks on Generic Functions
To: Dick Gabriel <RPG@SU-AI.ARPA>
cc: common-lisp-object-system@SU-AI.ARPA
In-Reply-To: The message of 27 Oct 86 23:34 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861028005001.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 27 Oct 86 2034 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Let's use another example:
Sure, PRINT brings in too many red herrings.
(DEFMETHOD COUNT-CONSTITUENTS (L)
(COND ((NOT (CONSP L)) 1)
(T (+ (COUNT-CONSTITUENTS (CAR L))
(COUNT-CONSTITUENTS (CDR L))))))
(GFLET ((COUNT-CONSTITUENTS ((L BAZOLA))
(+ JILLION-SKILLION (MAP-BAZOLA #'COUNT-CONSTITUENTS BAZOLA))))
(COUNT-CONSTITUENTS <some interesting thing>))
This will do the expected thing. The recursive calls to
COUNT-CONSTITUENTS in the first DEFMETHOD will invoke the specialized
version of COUNT-CONSTITUENTS, precisely because those recursive calls
pass through the function cell of the symbol COUNT-CONSTITUENTS.
This all falls out of the description of generic functions in my
`remarks' message. If Moon doesn't think that the recursive call to
COUNT-CONSTITUENTS in the GFLET will call the global (function cell)
definition of COUNT-CONSTITUENTS, then he doesn't understand the concepts
in my message.
Well, if I did, I certainly don't now! I'm quite confused. It doesn't
help that there are no messages from you in the archive containing the
string "GFLET" (nor "GLFET"), so I don't really know for sure what you
mean when you say GFLET. See below.
Is it true or is it false that (GFLET ((COUNT-CONSTITUENTS ...
makes the generic function that is the value of
(SYMBOL-FUNCTION 'COUNT-CONSTITUENTS) be one that calls the
specialized method, for the duration of its body? I think you're saying
above that it is true; that's why the recursive calls in the default
method can reach the specialized method. If the answer is "true", a
further refinement is, does the value of (SYMBOL-FUNCTION 'COUNT-CONSTITUENTS)
change to a different generic-function object, or is the original
generic-function object temporarily modified?
I had understood your previous messages to say the answer is "false",
and that a lexically defined generic function is a new generic function
object that is accessible through a lexically scoped name and is
isolated from the other generic function object accessible through a
global name.
I consulted the only two previous messages in the archive containing
the word GFLET. The one of 16 Oct from Gregor contrasts GFLABELS and
GFLET, which make an entirely new generic function lexically bound
to the name, with MLABELS, which dynamically adds methods to an existing
generic function. The one of 24 Oct from JonL says
Not only does lexicality shield the "(print z)" from using the global print,
but the call to 'maybe-modify-generic-function' is with a different object
than would be found in the symbol-function cell of PRINT. Even though there
may be side-effects upon the generic function, the lexical naming provides
a way of locally insulating these effects from the global environment.
Both of these seem to me to contradict what you're saying; that's okay,
they're not from you. Going back to your "remarks" message, which up until
today I thought I understood and agreed with, there is no direct discussion
of GFLET, but you do say
There is a second sort of `local' definition of methods that could make
sense - it is the one to which Gregor alluded in his message about my
anonymous generic function proposal. Suppose that a set of methods on the
symbol, FOO, has been defined. In a dynamic context the user might want
to temporarily extend FOO. I will use the name DFLET-METHOD; the user can
write:
(DFLET-METHOD ((FOO ((X C)) ...)) <form>)
and temporarily extend the generic function FOO to have this new method
associated with it during the execution of <form>. This, also, is a
reasonable programming methodology. I was curious about why Gregor thought
I meant something like DFLET-METHOD in my lexical generic function
proposal, even though I think my proposal was relatively clear on my
intention.
DFLET-METHOD seems to me to be the same as what you are calling
GFLET in the COUNT-CONSTITUENTS example above.
So I went back to your anonymous generic function proposal messages of
14 Oct and 15 Oct. They're mostly about syntax, but there is one
paragraph that bears on the issue at hand:
The generic-function-labels construct builds a generic function
which has nothing to do with any symbols. The methods are in the generic
function object. Presumably the construct logically does a MAKE-GENERIC and
some ADD-METHODS. It behaves with respect to symbol-function cells the
way that DEFUN and LABELS behave:
Is this the same as GFLET? This doesn't directly answer the question,
does the generic function that is the value of (SYMBOL-FUNCTION
'COUNT-CONSTITUENTS) change? But it seems to me that it implies
the answer is no, since LABELS has no effect on the value of
SYMBOL-FUNCTION.
At this point I am completely confused and have no idea what exactly
you are proposing.
Perhaps it is best to wait until these ideas are put into use before
putting them in the standard, but we must take care to not accidentally
preclude them from being implemented because they violate something in the
specification. Therefore, we should, at least, be considering these
possible extensions.
Certainly it is not the case that we are restricted to some combination of
ideas already implemented for inclusion in the standard - we are allowed
to think about them and refine them first.
I completely agree with these sentiments, by the way.
∂28-Oct-86 0631 edsel!bhopal!jonl@navajo.stanford.edu Remarks on Generic Functions
Received: from NAVAJO.STANFORD.EDU by SAIL.STANFORD.EDU with TCP; 28 Oct 86 06:31:21 PST
Received: by navajo.stanford.edu; Tue, 28 Oct 86 06:30:27 PST
Received: from bhopal.edsel.uucp by edsel.uucp (2.2/SMI-2.0)
id AA06452; Tue, 28 Oct 86 05:58:31 pst
Received: by bhopal.edsel.uucp (1.1/SMI-3.0DEV3)
id AA23319; Tue, 28 Oct 86 05:57:43 PST
Date: Tue, 28 Oct 86 05:57:43 PST
From: edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)
Message-Id: <8610281357.AA23319@bhopal.edsel.uucp>
To: navajo!Moon%STONY-BROOK.SCRC.Symbolics.COM@navajo.stanford.edu
Cc: navajo!common-lisp-object-system%SU-AI.ARPA@navajo.stanford.edu
In-Reply-To: David A. Moon's message of Mon, 27 Oct 86 21:25 EST
Subject: Remarks on Generic Functions
Is your question one to be answered:
"Yes, but what happens if Z is a list of FOOs?"
If so, then the answer is very clear -- the global definition is called on
the list of FOOs. Not a very interesting case, is it (especially since
Z in that code is only ever bound to FOOs and numbers)?
But I'm sure you could have figured that out yourself; so if you are trying
to say that the very nature of the second example -- the wrinkle on PRINT --
is such to make it so fundamentally different from the first -- the wrinkle
on SQRT -- that we may infer *nothing* from the amazing structural similarity
of the two programs, then I think you are dead wrong [it would help, Dave,
if you could be more direct when you want to say something like this, if
indeed this is what you were trying to say?]
Examples are perforce smaller than realistic applications (sad to say,
one of my "realistic applications" of LABELS goes on for pages; at least
it is circumscribed by the lexical context!). So imagine that, instead of
deferring to the global PRINT immediately, this wrinkle were to use GFLABELS
so that "PRINT" in the local code would recursively refer to the lexical
definition; and further imagine that the example is fleshed out using PRIN1
and/or PRINC on atomic data, so that there is no longer a question of
recursivity.
If you can believe that the "fleshed out" example has no more nits to pick
on it, then you should be able to comment on the alleged "amazing structural
similarity". In particular, is my interpretation of what lexicality should
mean for generic functions something around which we can, after discussion,
agree upon, or does it [rather than the simplified example illustrating it]
have fundamental flaws and gaps in it.
I know there are other interpretations for generic lexicality; that is not
any reason at all to give up on standardization in this area. Rather, the
whole point of discussion, such as occurred on Common Lisp, was to reduce
the number of options to something that was either consensually agreed upon,
or that at least had the support of a large majority.
Surely the only premature decision is one which concludes that no such
agreement can possibly be reached in the forseeable future.
-- JonL --
∂28-Oct-86 0631 edsel!bhopal!jonl@navajo.stanford.edu Lexical GFLABELS versus "dynamic" GFLABELS
Received: from NAVAJO.STANFORD.EDU by SAIL.STANFORD.EDU with TCP; 28 Oct 86 06:31:53 PST
Received: by navajo.stanford.edu; Tue, 28 Oct 86 06:31:09 PST
Received: from bhopal.edsel.uucp by edsel.uucp (2.2/SMI-2.0)
id AA06557; Tue, 28 Oct 86 06:28:09 pst
Received: by bhopal.edsel.uucp (1.1/SMI-3.0DEV3)
id AA23325; Tue, 28 Oct 86 06:27:23 PST
Date: Tue, 28 Oct 86 06:27:23 PST
From: edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)
Message-Id: <8610281427.AA23325@bhopal.edsel.uucp>
To: navajo!common-lisp-object-system%SU-AI.ARPA@navajo.stanford.edu
Subject: Lexical GFLABELS versus "dynamic" GFLABELS
It appears to me that RPG slipped up in his COUNT-CONSTITUENTS example
in that the globally-appearing DEFMETHOD should have been one of the
clauses in the lexically-local definition. The reason I say "slipped
up" is that in subsequent remarks he invokes the case of "dynamic" GFLET
(which temporarily modifies the symbol-function cell of COUNT-CONSTITUENTS)
as a different paradigm. Moon commented upon this at length.
Either way, an interesting question pops up. Suppose we use GFLABELS
rather than GFLET in that example -- then what does the #'COUNT-CONSTITUENTS
refer to?
(GFLABELS ((COUNT-CONSTITUENTS ((L BAZOLA))
(+ JILLION-SKILLION (MAP-BAZOLA #'COUNT-CONSTITUENTS BAZOLA))))
(COUNT-CONSTITUENTS <some interesting thing>))
Should it be interpreted as (SYMBOL-FUNCTION 'COUNT-CONSTITUENTS) -- i.e.,
the global definition -- or should it be specially interpreted to mean the
lexically-local definition? I believe the same question was asked of the
Common Lisp mailing list not too long ago, and I don't remember if there was
a clear consensus.
It is clear that #'FOO ==> (FUNCTION FOO), and page 87 of CLtL seems to
imply that (FUNCTION FOO) ==> (SYMBOL-FUNCTION 'FOO); but that may just
be an oversight.
Regardless of the "genericity" question, it would be a shame if one couldn't
specify the "current, lexical definition" as a functional argument somehow.
And of course, the answer ought to be exactly the same for lexical generic
functions as it is for lexical "ordinary" functions.
-- JonL --
P.S. It would appear that examples that are somehow recursive are bad
examples to illustrate anything about FLET/GFLET; at the very least,
one may find himself being driven to LABELS/GFLABELS.
∂28-Oct-86 0753 RPG GLFET
To: common-lisp-object-system@SAIL.STANFORD.EDU
Hm. When I glanced at Jonl's message about GFLET and saw the
PRINT example, I thought he was talking about what I had called
DFLET-METHOD. I see that he isn't. So, Moon's comment about
this code:
(generic-function-let
(((print (x &optional (stream *standard-output*))
;; default method just goes back to global print definition
(let ((*print-structure* nil))
(PRINT x stream))) ;Escape about of GF-land
(print ((x foo) &optional (stream *standard-output*))
;; 'foo' instances need more visibility
(let ((*print-structure* t))
(print x t)))))
. . .
(maybe-modify-generic-function #'print)
. . .
(print z)
. . .
)
is right. Once the PRINT in capital letters is invoked, we cannot come
back into the world defined by the GENERIC-FUNCTION-LET. Using DFLET-METHOD,
one could write:
(let ((*print-structure* nil))
(declare (special *print-structure*))
(DFLET-METHOD
((print ((x foo) &optional (stream *standard-output*))
;; 'foo' instances need more visibility
(let ((*print-structure* t))
(print x t)))))
. . .
(print z)
. . .
)
to get approximately the behavior Jonl discusses.
To emphasize:
1. Generic-function-let creates a new generic function, unrelated
to any other that is associated with a symbol whose print name
is the same as the identifier name in the generic-function-let
form. The same remark holds for generic-function-labels.
2. DFLET-METHOD temporarily modifies a generic function associated
with a symbol (or adds a new generic function to a symbol which
does not have one).
The code for COUNT-CONSTITUENTS should read:
(DEFMETHOD COUNT-CONSTITUENTS (L)
(COND ((NOT (CONSP L)) 1)
(T (+ (COUNT-CONSTITUENTS (CAR L))
(COUNT-CONSTITUENTS (CDR L))))))
(DFLET-METHOD ((COUNT-CONSTITUENTS ((L BAZOLA))
(+ JILLION-SKILLION (MAP-BAZOLA #'COUNT-CONSTITUENTS BAZOLA))))
(COUNT-CONSTITUENTS <some interesting thing>))
I apologize for thinking that GFLET was *not* the same GENERIC-FUNCTION-LET
and that GFLET was the same as DFLET-METHOD; the example using PRINT
threw me off.
-rpg-
∂28-Oct-86 1112 Moon@STONY-BROOK.SCRC.Symbolics.COM Lexical GFLABELS versus "dynamic" GFLABELS
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Oct 86 11:12:27 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 144476; Tue 28-Oct-86 14:05:02 EST
Date: Tue, 28 Oct 86 14:03 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Lexical GFLABELS versus "dynamic" GFLABELS
To: common-lisp-object-system@SU-AI.ARPA
In-Reply-To: <8610281427.AA23325@bhopal.edsel.uucp>
Message-ID: <861028140344.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Tue, 28 Oct 86 06:27:23 PST
From: edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)
[main text of message deleted]
P.S. It would appear that examples that are somehow recursive are bad
examples to illustrate anything about FLET/GFLET; at the very least,
one may find himself being driven to LABELS/GFLABELS.
No, I think they are excellent examples, because they tend to highlight
the difference between regular functions and generic functions. Regular
functions are defined in one place, so it's obvious how to shadow one
definition with another. Generic functions are defined in many places
(with methods), so all these additional issues arise about exactly what
it means to shadow one definition with another. Recursive examples help
bring out the issues.
∂28-Oct-86 1459 Pavel.pa@xerox.com Re: Lexical GFLABELS versus "dynamic" GFLABELS
Received: from NAVAJO.STANFORD.EDU by SAIL.STANFORD.EDU with TCP; 28 Oct 86 14:59:34 PST
Received: from XEROX.COM by navajo.stanford.edu with TCP; Tue, 28 Oct 86 14:16:40 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 28 OCT 86 12:33:58 PST
Date: 28 Oct 86 12:32 PST
From: Pavel.pa@xerox.com
Subject: Re: Lexical GFLABELS versus "dynamic" GFLABELS
In-Reply-To: edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)'s
message of Tue, 28 Oct 86 06:27:23 PST
To: edsel!bhopal!jonl@navajo.stanford.edu
Cc: navajo!common-lisp-object-system%SU-AI.ARPA@navajo.stanford.edu
Message-Id: <861028-123358-4378@Xerox>
Date: Tue, 28 Oct 86 06:27:23 PST From:
edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)
It is clear that #'FOO ==> (FUNCTION FOO), and page 87 of CLtL
seems to imply that (FUNCTION FOO) ==> (SYMBOL-FUNCTION 'FOO); but
that may just be an oversight.
Actually, Guy's list of typo's contains a correction for the paragraph
in question on page 87. The new text reads:
``In particular, if FN is a symbol, the functional definition of that
name is returned, which is that established by the innermost
lexically-enclosing FLET, LABELS, or MACROLET construct, if there is
one, or else the global functional definition of the symbol (see
SYMBOL-FUNCTION).''
This probably also wants a note about it being an error to use #'foo
when inside an unshadowed MACROLET definition of foo,but at least it's
clear on the meaning of #' inside lexical-function binding forms.
Pavel
∂28-Oct-86 1931 Moon@STONY-BROOK.SCRC.Symbolics.COM new files on [CLS,LSP]
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Oct 86 19:30:26 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 144969; Tue 28-Oct-86 22:30:33 EST
Date: Tue, 28 Oct 86 22:29 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: new files on [CLS,LSP]
To: Linda DeMichiel <LGD@SU-AI.ARPA>
cc: common-lisp-object-system@SU-AI.ARPA
In-Reply-To: The message of 27 Oct 86 22:36 EST from Linda DeMichiel <LGD@SAIL.STANFORD.EDU>
Message-ID: <861028222914.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 27 Oct 86 1936 PST
From: Linda DeMichiel <LGD@SAIL.STANFORD.EDU>
The new files are functi.tex, functi.dvi, concep.tex, and concep.dvi.
We still can't print these DVI files (I only tried concep.dvi this time).
They make our postscript printers run out of memory and crash.
This TEX-based document production technique is not working very well so far.
∂28-Oct-86 2004 LGD printing files
To: moon@SCRC-STONY-BROOK.ARPA
CC: common-lisp-object-system@SAIL.STANFORD.EDU
Perhaps you should have your facilities people check into your memory
problems (or possible problems with PostScript), since you were
running out of memory even on the files we produced with stripped-down
fonts.
I have successfully printed the .dvi files on [CLS,LSP] on both the
Imagen and Dover printers at Stanford as well as on our Imagen at
Lucid. At Lucid we've printed even more complex documentation files
without any problems using our Laserwriter and PostScript.
If you have access to printers at MIT, as I think you mentioned, that
might be a workaround. Otherwise, we can arrange to send hardcopy.
∂29-Oct-86 0214 DUSSUD@martha Re: Instance transformation pr
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Oct 86 02:14:21 PST
Received: from ti-csl by csnet-relay.csnet id am00384; 28 Oct 86 13:23 EST
Received: from Martha (p-lorre.ARPA) by tilde id AA18124; Tue, 28 Oct 86 10:06:57 cst
From: DUSSUD%TILDE%ti-csl.csnet@CSNET-RELAY.ARPA
To: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Cc: Common-Lisp-Object-System@SU-AI.ARPA
Subject: Re: Instance transformation pr
Date: 28-Oct-86 10:02:12
Sender: DUSSUD@martha
Message-Id: <DUSSUD.2739888129@Martha>
Dave,
A proposed, but rejected, extension to Common Lisp was
(setf (values (point-rho p) (point-theta p))
(convert-to-r-t x y))
I forget why this was rejected. Probably the majority of the Common Lisp
committee couldn't see in 1983 any applications for it.
This seems like the appropriate syntax for such a feature, rather than
adding a new special form.
By the way it's trivial to implement, but not in a portable way. What I
mean is that it is trivial to add to most setf substrates.
I think we can implement it in a portable way, it may not be the best implementation
for some architecture though.
(define-setf-method values (&rest places)
(if (every #'symbolp places )
(let ((g (gensym)))
(values nil nil (list g)
`(multiple-value-setq ,places ,g)
g))
(let ((g (gensym))
(ltemp (mapcar #'(lambda (ignore )
(declare (ignore ignore))
(gensym))
places)))
(values nil nil (list g)
`(multiple-value-bind ,ltemp ,g
,@(mapcar #'(lambda (x y) `(setf ,x ,y)) places ltemp))
g))))
Patrick.
∂29-Oct-86 0510 edsel!bhopal!jonl@navajo.stanford.edu Lexical GFLABELS versus "dynamic" GFLABELS
Received: from NAVAJO.STANFORD.EDU by SAIL.STANFORD.EDU with TCP; 29 Oct 86 05:10:45 PST
Received: by navajo.stanford.edu; Wed, 29 Oct 86 05:10:00 PST
Received: from bhopal.edsel.uucp by edsel.uucp (2.2/SMI-2.0)
id AA01454; Wed, 29 Oct 86 04:33:56 pst
Received: by bhopal.edsel.uucp (1.1/SMI-3.0DEV3)
id AA26023; Wed, 29 Oct 86 04:32:59 PST
Date: Wed, 29 Oct 86 04:32:59 PST
From: edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)
Message-Id: <8610291232.AA26023@bhopal.edsel.uucp>
To: navajo!Moon%STONY-BROOK.SCRC.Symbolics.COM@navajo.stanford.edu
Cc: navajo!common-lisp-object-system%SU-AI.ARPA@navajo.stanford.edu
In-Reply-To: David A. Moon's message of Tue, 28 Oct 86 14:03 EST
Subject: Lexical GFLABELS versus "dynamic" GFLABELS
Date: Tue, 28 Oct 86 14:03 EST
From: David A. Moon <navajo!Moon@STONY-BROOK.SCRC.Symbolics.COM>
Date: Tue, 28 Oct 86 06:27:23 PST
From: edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)
. . .
P.S. It would appear that examples that are somehow recursive are bad
examples to illustrate anything about FLET/GFLET; at the very
least, one may find himself being driven to LABELS/GFLABELS.
No, I think they are excellent examples, because they tend to highlight
the difference between regular functions and generic functions. . . .
Well, I'm glad you now think they are excellent examples, but I'm not
so sure of the analysis which follows in your note. The fact that one
may want to write one of them as a recursive definition (e.g., the
modified "print", but extended to cover more cases) highlights the
defined difference between FLET and LABELS -- it doesn't really say
anything about the distribution of defmethods.
Distributing the source code across non-lexical scope is entirely a
separate matter. The whole point of the sqrt/print examples was to
provide some evidence, based on real experience with lexical functions,
to rebut the thesis: "One would never want to use generic functions
without breaking the lexical barrier". I think a desire to define two
different methods for the same generic function, but in two different
lexical locales, would probably have very little to do with whether or
not the function is recursive; do you have some example in mind where
the recursiveness is the key?
I fully agree that many, if not most, uses of generic functions will find
their defmethods widely distributed (i.e., not suitable for making a lexical
function); but then again, looking at a lot of recent Common Lisp code, I see
that most functions aren't defined using FLET or LABELS either.
-- JonL --
∂29-Oct-86 0919 kempf%hplabsc@hplabs.HP.COM Re: printing files
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 29 Oct 86 09:19:19 PST
Received: from hplabsc by hplabs.HP.COM ; Wed, 29 Oct 86 09:14:16 pst
Received: by hplabsc ; Wed, 29 Oct 86 08:44:05 pst
Date: Wed, 29 Oct 86 08:44:05 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8610291644.AA08223@hplabsc>
To: LGD@SAIL.STANFORD.EDU, moon@SCRC-STONY-BROOK.ARPA
Subject: Re: printing files
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
I have also been unable to print DVI files obtained off of SAIL.
I haven't tried the latest, but the previous batch wouldn't work.
The tex people here said we probably didn't have the right fonts.
I have, however, been able to re-tex the .tex files using LaTex,
and thereby produce hardcopy.
Jim Kempf kempf@hplabs
∂29-Oct-86 1035 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Instance transformation pr
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Oct 86 10:34:47 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 145401; Wed 29-Oct-86 12:46:59 EST
Date: Wed, 29 Oct 86 12:45 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Instance transformation pr
To: DUSSUD%TILDE%ti-csl.csnet@CSNET-RELAY.ARPA
cc: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <DUSSUD.2739888129@Martha>
Message-ID: <861029124535.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 28-Oct-86 10:02:12
From: DUSSUD%TILDE%ti-csl.csnet@CSNET-RELAY.ARPA
A proposed, but rejected, extension to Common Lisp was
(setf (values (point-rho p) (point-theta p))
(convert-to-r-t x y))
I think we can implement it in a portable way, it may not be the best implementation
for some architecture though.
(define-setf-method values (&rest places)
(if (every #'symbolp places )
(let ((g (gensym)))
(values nil nil (list g)
`(multiple-value-setq ,places ,g)
g))
(let ((g (gensym))
(ltemp (mapcar #'(lambda (ignore )
(declare (ignore ignore))
(gensym))
places)))
(values nil nil (list g)
`(multiple-value-bind ,ltemp ,g
,@(mapcar #'(lambda (x y) `(setf ,x ,y)) places ltemp))
g))))
I don't think this works. At least in some implementations you will
end up with code looking like
(let ((#:g0001 (foo x y)))
(multiple-value-bind (#:g0002 #:g0003) #:g0001
(setf (bar a) #:g0002)
(setf (baz b) #:g0003)
#:g0001))
for (setf (values (bar a) (baz b)) (foo x y)), which of course
sets (baz b) to nil.
∂29-Oct-86 1615 kempf%hplabsc@hplabs.HP.COM Re: Local Lexical Generic Functions
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 29 Oct 86 16:14:50 PST
Received: from hplabsc by hplabs.HP.COM ; Wed, 29 Oct 86 16:13:56 pst
Received: by hplabsc ; Wed, 29 Oct 86 16:12:25 pst
Date: Wed, 29 Oct 86 16:12:25 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8610300012.AA20272@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Local Lexical Generic Functions
As an additional data point, we have a CommonLoops user here
who wanted to use MLET, but it isn't in our version of CommonLoops.
His application is a window system, and he wanted it to do some
customized window initialization.
Jim Kempf kempf@hplabs
PS: Is MLET in the currently on parcvax version of CommonLoops?
If so, then we may be able to get some user reaction to local
lexical generics.
∂29-Oct-86 1755 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Dispatching on optional/keyword arguments
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Oct 86 17:54:52 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 145870; Wed 29-Oct-86 20:54:27 EST
Date: Wed, 29 Oct 86 20:52 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Dispatching on optional/keyword arguments
To: Masinter.pa@XEROX.COM
cc: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: The message of 23 Oct 86 19:01 EDT from Masinter.pa@Xerox.COM,
<861023-160755-1667@Xerox>,
The message of 23 Oct 86 21:59 EDT from Masinter.pa@Xerox.COM,
<861024-103930-1108@Xerox>
Message-ID: <861029205259.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Yes, I think your proposal is a ninth proposal, not completely identical
to any of the eight I had dredged out of the mail. I archived it together
with my message for the benefit of any future attempt to deal with the
problem of dispatching on optional/keyword arguments.
The thing that I don't like about your proposal can be expressed very
succinctly, I think: It doesn't really provide the ability to specialize
on optional arguments from the caller's point of view. Suppose I have
a generic function BLATZ and I can call it with either one or two
arguments. I'd like to be able to say that the second argument to BLATZ
is optional and defaults to the value of *STANDARD-OUTPUT*. In your
proposal, if there any methods that specialize on the second argument,
the two forms (BLATZ X) and (BLATZ X *STANDARD-OUTPUT*) don't behave
identically. Thus I don't think you can really say that the second
argument is optional; in order to get the full behavior the caller
has to supply that argument.
∂30-Oct-86 1333 Moon@STONY-BROOK.SCRC.Symbolics.COM new files on [CLS,LSP]
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Oct 86 13:33:12 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 146685; Thu 30-Oct-86 16:31:47 EST
Date: Thu, 30 Oct 86 16:30 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: new files on [CLS,LSP]
To: Linda DeMichiel <LGD@SU-AI.ARPA>
cc: common-lisp-object-system@SU-AI.ARPA
In-Reply-To: <861028222914.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <861030163005.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Tue, 28 Oct 86 22:29 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Date: 27 Oct 86 1936 PST
From: Linda DeMichiel <LGD@SAIL.STANFORD.EDU>
The new files are functi.tex, functi.dvi, concep.tex, and concep.dvi.
We still can't print these DVI files (I only tried concep.dvi this time).
They make our postscript printers run out of memory and crash.
This TEX-based document production technique is not working very well so far.
By applying a postscript expert, a patch to the 68000 software in the
Laserwriter that makes it (sometimes) give an explanation of what
happened when something goes wrong instead of just wiping itself out and
crashing, and a lot of experiments, we have made a little progress on this.
We also found that when the printer claims to have run out of memory,
sometimes it is lying and sometimes it is telling the truth.
We found a problem, caused by the way you do ligatures, that was making
our printers crash. This was really a bug in our printer driver and after
fixing it we can print some of your files. For example, we can print
the symfun.dvi file you made a while ago that uses only 8 fonts instead
of 12.
We still can't print concep.dvi. This may really be a memory problem.
It requires 185,772 bytes of bitmap fonts, and I'm told there is only
240K bytes memory available in total. Perhaps the other overhead takes
more than 55K bytes. I don't understand why the amount of memory designed
into the printer is so small. I also don't understand why you need to
use 12 different fonts in this document. We also can't print functi.dvi,
which requires 151,108 bytes of bitmap fonts.
Experimentation shows that the amount of fonts that can be loaded
without crashing the printer is in the range of 90K to 140K bytes. Part
of the problem with concep.dvi, however, seems to have something to do
with the illustration on page 5 taking a lot of memory. I don't really
understand what's going on here yet, but a useful experiment would be
possible if you make versions of concep and functi with fewer fonts,
similar to symfun. If those versions will print, perhaps we can stick
with the smaller number of fonts and avoid all this pain.
I was able to get a complete listing of concep.dvi by piecing together
the output from all of my experiments, which means that every page is
printable individually (printing portions of the document, rather than
printing it all at once, tends to work better because a portion of
the document usually uses fewer characters than the whole document,
so the memory occupied by fonts is smaller).
On another front, it took me most of the week to get SAIL to disgorge
an uncorrupted copy of functi.dvi. The Arpanet is really going down
the toilet these days.
∂30-Oct-86 1452 DUSSUD%Jenner%ti-csl.csnet@CSNET-RELAY.ARPA
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 30 Oct 86 14:52:44 PST
Received: from ti-csl by csnet-relay.csnet id af02666; 30 Oct 86 12:36 EST
Received: from Jenner (jenner.ARPA) by tilde id AA02018; Thu, 30 Oct 86 10:51:30 cst
To: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Cc: Common-Lisp-Object-System@SU-AI.ARPA
Date: 30-Oct-86 10:42:31
From: DUSSUD%Jenner%ti-csl.csnet@CSNET-RELAY.ARPA
Message-Id: <DUSSUD.2740063349@Jenner>
(define-setf-method values (&rest places)
(if (every #'symbolp places )
(let ((g (gensym)))
(values nil nil (list g)
`(multiple-value-setq ,places ,g)
g))
(let ((g (gensym))
(ltemp (mapcar #'(lambda (ignore )
(declare (ignore ignore))
(gensym))
places)))
(values nil nil (list g)
`(multiple-value-bind ,ltemp ,g
,@(mapcar #'(lambda (x y) `(setf ,x ,y)) places ltemp))
g))))
I don't think this works. At least in some implementations you will
end up with code looking like
(let ((#:g0001 (foo x y)))
(multiple-value-bind (#:g0002 #:g0003) #:g0001
(setf (bar a) #:g0002)
(setf (baz b) #:g0003)
#:g0001))
for (setf (values (bar a) (baz b)) (foo x y)), which of course
sets (baz b) to nil.
OOPS, you're right!
Sorry about that.
Patrick.
∂30-Oct-86 1728 LGD stripped down versions of files
To: moon@SCRC-STONY-BROOK.ARPA
CC: common-lisp-object-system@SAIL.STANFORD.EDU
I've hacked up stripped-down versions of the concepts and functions files
using fewer fonts. These versions also lack the type diagram, but are
otherwise identical to the current versions of functi.tex and concep.tex.
The new files are symfun.dvi and symcon.dvi.
Linda
∂31-Oct-86 1603 DUSSUD%Jenner%ti-csl.csnet@CSNET-RELAY.ARPA A proposal for a finer grained method combination selection.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 31 Oct 86 16:03:10 PST
Received: from ti-csl by csnet-relay.csnet id ag10983; 31 Oct 86 17:50 EST
Received: from Jenner (jenner.ARPA) by tilde id AA18545; Fri, 31 Oct 86 16:22:10 cst
To: common-lisp-object-system@SU-AI.ARPA
Cc:
Subject: A proposal for a finer grained method combination selection.
Date: 31-Oct-86 16:12:26
From: DUSSUD%Jenner%ti-csl.csnet@CSNET-RELAY.ARPA
Message-Id: <DUSSUD.2740169545@Jenner>
A proposal for a finer grained method combination selection.
In Dave's revised write-up on method combination, the method combination
technique is attached to the generic function. I see two reasons for
proposing an alternative:
1. A generic function implements a contract between the object
implementation and its callers. However method combination is a contract
between methods within a method precedence list (referred as "sorted list of
the available method" by Dave in Step 2 of his procedure for method combination).
2. When a generic function implements functionality for orthogonal sets of
classes, it may be that these sets need different method combinations.
Proposal:
- It is possible to specialize the method combination for a given method precedence list.
Since a method precedence list is determined by a generic function and a number of type
specifiers equal to the length of the qualified argument list of the generic function,
I propose to add the following function:
(add-method-combination method-combination generic-function &rest type-specifiers )
will define the method combination to use for the method precedence list
defined by the generic-function and the type-specifiers. The type-specifiers must be
acceptable as argument specifiers for a method on the generic function.
(I am sure somebody can think of a better name for it).
- I propose to change the procedure that Dave describes in his proposal for method combination,
as follows:
2. Sort the available methods into a precedence order.
To compare the precedence of two methods, examine their parameter
specializers in order from left to right. An unspecialized parameter has a
default parameter specializer of T. The first pair of parameter
specializers that are not equal determine the precedence. Method X is more
specific than method Y if method X's parameter specializer is earlier than
method Y's parameter specializer in the class precedence list of the class
of the argument. Since the methods are available for this argument, it is
guaranteed that their parameter specializers are present in the class
precedence list of the class of the argument.
T is implied at the very end of each class precedence list, so it is less
specific than any other class. (QUOTE individual) is more specific than
any class.
The resulting list of available methods is sorted with the most specific
method first and the least specific method at the end.
2.1 Sort the available method combinations into a precedence order
They are sorted the same way methods are sorted.
3. Apply method combination.
--The first sentence:
<The method combination technique specified for the generic function receives
the sorted list of available methods and returns a Lisp form.>
--would be replaced by:
<The first method combination technique in the method combination precedence list
receives the sorted list of available methods and returns a Lisp form.>
This form
contains calls to some or all of the methods, defines the value(s) to be
returned by the generic function, and optionally makes some of the methods
reachable via CALL-NEXT-METHOD, rather than calling them directly.
Open issues:
As Dave says in his proposal, for the method cobination technique:
"If a method is available but matches none of the qualifier-patterns, the
fact that the method is not valid with this type of method combination is
automatically reported as an error or as a warning as appropriate."
According to this proposal we could pick up some method suitable for another
method combination style because this method can appear in two method
precedence lists having incompatible method combinations.
Should that be considered as an error?
Patrick.
∂05-Nov-86 0850 hpfclp!robert@hplabs.HP.COM discussion wanted
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 5 Nov 86 08:50:17 PST
Received: by hplabs.HP.COM ; Wed, 5 Nov 86 08:48:35 pst
From: hpfclp!robert@hplabs.HP.COM
Received: by hpfclp; Wed, 5 Nov 86 09:32:26 mst
Date: Wed, 5 Nov 86 09:32:26 mst
Return-Path: <hpfclp!robert>
Received: from hpfcnml.UUCP; Wed, 5 Nov 86 09:31:45
To: common-lisp-object-system@sail.stanford.edu
Subject: discussion wanted
I am Robert Heckendorn with Hewlett-Packard in Fort Collins, Colorado.
It is here that Hewlett-Packard's version of CommonLisp was developed.
I have been following this discussion with much interest since I was
included on the mailing list at OOPSLA. My experience with object
oriented programming has been limited; so, though I am tempted, I will
try not to become an extra cook in the kitchen.
It seems the view of people that I deal with in the LISP community
generally may be different from what you may believe is their view.
Here is what many I have talked to have been saying:
"There is a new standard for object oriented programming called
CommonLoops that has been defined. It would nice to use it to do our
code because it is a standard. We won't find our objects code becoming
obsolete for that reason."
I even get flack for not already having this standard! Just thought you
would want to know, if you didn't already.
There are several things that worry me about this ever-growing standard.
I am not trying to change the standard. I just want to examine the
rationale and tradeoffs.
This standard is immense. I am worried that even though the proposal is
going to be well thought out, its usability is threatened by its size.
As pointed out by practically the entire OOPSLA panel on learnability,
one of the major contributors to the learnability of an object oriented
language is simplicity. Give them too many options and they balk or get
mired in details. I am worried about our users. I have to ask is all
this really necessary for the standard or is it just a good thing to
have on a rainy day?
People need a model. My thanks to Dick for his short monograph on his
model for generic functions. The programmer on the street needs a good
model for this new way of looking at things. I would like to see some
more discussion such as Dick's. How do we tell these folks to think
about all this method combination, generic functions and the
relationship between a lattice of types and selection of methods?
Another big point that came out of OOPSLA was that there is little known
about the area of methodology for object oriented programming. This
dearth of knowledge is for, what has been referred to as, the "classical
object", that is only one argument being used for the discrimination of
method. Is it appropriate to advance as a standard a scheme that
involves multimethods where even less is known about how to use this
"feature"? What do we know about methodologies for this model of object
oriented programming?
I have been asked by several in an annoyed tone, "Why are they throwing
out the classical way of doing objects?" What can I say to them? Has
it been shown more useful? I'm not saying that it isn't useful. People
want to know that many people have already found it useful by using it.
Is there a paper or bit of research that will make both them and me feel
better about this decision? The rationale for selecting multimethods
should be discussed so that at least it can be written up nicely and put
in the "Design Rationale" chapter.
One of the biggest complaints about Objects is speed. I hear the
complaints from our users. I see that PPI makes speed one of their big
selling points, recognizing it is a dragon that must be slain. I have
seen some talk about speed on this notes group but not much. The
standard has to be one that not only gives features but allows speed or
people just won't use it. Speed must be thought of during design or it
will be a hack. What kind of assumptions can the compiler make about
staticness of class and generic function definitions? What kind of
declarations can be used to increase the knowledge that interpretors and
compilers will have? What is not allowed to be known before run time?
I know it isn't as fun to talk about some of the above areas, but they
do need more air time in this group.
Here are some general questions that I have or have been asked and
really could not answer knowledgeably.
Is there going to be a portable implementation of Classes for Common
Lisp?
What is the future of CommonLoops?
When do you think the public will see the "final document"? People want
to know when can I start using the new standard. What do I tell them?
What is the process that you must go through to make this officially
part of a standard?
thanks,
Robert Heckendorn
robert%hpfclp@hplabs.HP.COM
∂05-Nov-86 1255 RPG Next Step
To: common-lisp-object-system@SAIL.STANFORD.EDU
Because it appears that FUNCTION.TEX is essentially stable and because the
deadline for sending it to X3J13 approaches, Linda and I are going to
start going over it to
1. make it read like a specification (dull but precise);
2. make sure exactly the decisions we reached are discussed; and
3. turn it into TEX.
If there are major comments about the contents of FUNCTION.TEX,
you should send them soon.
-rpg-
∂05-Nov-86 2129 Moon@STONY-BROOK.SCRC.Symbolics.COM Next Step
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 5 Nov 86 21:28:55 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 151510; Wed 5-Nov-86 22:40:00 EST
Date: Wed, 5 Nov 86 22:39 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Next Step
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 5 Nov 86 15:55 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861105223946.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 05 Nov 86 1255 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Because it appears that FUNCTION.TEX is essentially stable and because the
deadline for sending it to X3J13 approaches, Linda and I are going to
start going over it to
1. make it read like a specification (dull but precise);
2. make sure exactly the decisions we reached are discussed; and
3. turn it into TEX.
If there are major comments about the contents of FUNCTION.TEX,
you should send them soon.
Well, bear in mind that I have -never- seen the contents of that file,
so if you haven't heard comments on it from me it doesn't mean that I
agree with what it says. I don't even know what it says. I guess
Linda sent Sonya a hardcopy of it and I can try to get a copy of that.
If you don't hear from me please assume that you haven't heard from me.
The supposed ability for us to print copies of these files and stay
in constant communication hasn't worked very well, partly because the
Arpanet has been almost continuously down (or at least SU-AI hasn't
been communicating) for the past several weeks. Mail seems to get
through with a delay of a day or so. This is not caused by anything
local to Symbolics, the same effect is observed from other hosts.
I'm not sure it's a good idea to send incomplete drafts to the X3J13
committee. Sending out the list of functions without any conceptual
background explaining what they do seems to me to serve no purpose,
other than perhaps to demonstrate that we haven't been sitting on our
hands.
∂05-Nov-86 2235 Moon@STONY-BROOK.SCRC.Symbolics.COM stripped down versions of files
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 5 Nov 86 22:34:48 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 151571; Thu 6-Nov-86 01:33:01 EST
Date: Thu, 6 Nov 86 01:32 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: stripped down versions of files
To: Linda DeMichiel <LGD@SAIL.STANFORD.EDU>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 30 Oct 86 20:28 EST from Linda DeMichiel <LGD@SAIL.STANFORD.EDU>
Message-ID: <861106013249.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 30 Oct 86 1728 PST
From: Linda DeMichiel <LGD@SAIL.STANFORD.EDU>
I've hacked up stripped-down versions of the concepts and functions files
using fewer fonts. These versions also lack the type diagram, but are
otherwise identical to the current versions of functi.tex and concep.tex.
The new files are symfun.dvi and symcon.dvi.
Thanks. I finally was able to get those files over here, and print them
out. I hope I'll be able to start reading them tomorrow. I'll
coordinate any corrections through Sonya (with mail where I think issues
need general discussion). Please use the same fewer-fonts mode for
future drafts, since that will make it much easier for us (always
assuming that whoever is responsible for maintaining the Arpanet fixes
the Arpanet problems).
I think the type diagram could safely be put back in, although that may
not be worthwhile since I believe the diagram as it stands (I have a
copy dated Oct 27 18:17) is completely different from what we agreed to
and will have to be redrawn.
∂06-Nov-86 0700 Masinter.pa@Xerox.COM Re: discussion wanted
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Nov 86 07:00:18 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 06 NOV 86 06:34:45 PST
Date: 6 Nov 86 04:23 PST
From: Masinter.pa@Xerox.COM
Subject: Re: discussion wanted
In-reply-to: hpfclp!robert@hplabs.HP.COM's message of Wed, 5 Nov 86
09:32:26 mst
To: hpfclp!robert@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <861106-063445-1053@Xerox>
This is a colloquial reply to your question -- a lot of this has been
written before, but I thought I'd give you a direct reply....
re size of standard: the document looks big, but its mainly because a
lot of words were used to describe simple things.... probably the thing
can get smaller before it gets to be a standard.. Multimethods actually
makes Common Lisp plus this smaller than not having them, since you'd
have to explain why they're not there.
Here's a simple model that I've found effective in telling people about
it:
Preface: Common Lisp already has functions & types. You define new
functions with defun, new types with defstruct. The types already form a
lattice.
In the object system, there's a way of defining functions in pieces;
each piece is a method, which only applies when the arguments match. You
get to it the same way you get to anything in Lisp, by doing function
call -- its just that what you get to might be some pieces that somehow
decide which one applies rather than a single function. Its nice and
simple that you can talk about matching any of the arguments rather than
just one.
In the object system, you define new types pretty much as before, except
that you use defclass instead of defstruct, mainly because the defstruct
syntax just wasn't extensible and had the defaults wrong; defclass has a
few more options than defstruct.
Classes kind of are a way of cleaning up what a "type" is; there's two
ways of explaining it: one is that you say: well, there are classes, and
then there are some other kinds of type descriptions which aren't them,
things like (satisfies primep). The other way to explain it is that you
take what COmmon Lisp calls "types" and split 'em up. (The only
difference between the two descriptions is where you start.) What's
important here is that all of the datatypes of common lisp, things like
numbers & strings and the like, are classes too.
Finally, and this adds a bit to the size of the standard but isn't too
important for most beginning users, a lot of how the object system works
inside is actually modifiable in a controlled way using "meta-objects",
i.e., a class is an object and a generic function is an object too, and
you can define new kinds of them. A lot of the words in the standard
have to do with allowing that; maybe a users guide would put it in an
appendix.
As for performance, it was a central issue in the design of CommonLoops
that it run reasonably on machines like yours. Its just been our
experience that you get nearly as much out of caching as you do out of
trying to hack declarations: there are some cases where declarations get
you more, but there are lots of cases where they get you less. So the
performance emphasis was on caching techniques rather than on
compilation techniques, for which we have mainly handwaves (= reasonable
arguments that compiler optimization of method lookup is feasible with a
moderate amount of work, basic approaches, etc.)
Nobody's throwing out the classical way of doing objects -- its just
that embedding it in functions & function call and types makes lisp +
objects simpler than "Doing Objects" using methods that aren't functions
and types that aren't like classes.
One thing that people relate to is that there's a natural equivalence
between a typical Common Lisp style:
(defun entryfn (arg1 arg2)
(check-type arg1 number)
(check-type arg2 string)
...)
and the single implementation methods
(defmethod entryfn ((arg1 number) (arg2 string)) ...)
and between the style of
(defun showem (arg1 arg2)
(typecase arg1
(star (print-star arg1))
(triangle (typecase arg2
(laser-printer (print-direct arg1 arg2))
(t (print-triangle-with-lines arg1 arg2))))...
and
(defmethod showem ((arg1 star) arg2) (print-star arg1 arg2))
(defmethod showem ((arg1 triangle) arg2)
(print-triangle-with-lines arg1 arg2))
(defmethod showem ((arg1 triangle) (arg2 laser-printer))
(print-direct arg1 arg2))
My typical demo is
(defmethod sum (x y) `(+ ,x ,y))
(sum 1 2)
(sum 'a 'b)
(sum * **)
(defmethod sum ((x number) (y number)) (+ x y))
(sum 1 2)
(sum 'a 'b)
(sum * **)
(defmethod sum (x (y list))
(if (eq (car y) '+) `(+ x ,@(cdr y)) (call-next-method)))
(sum 1 2)
(sum 'a 'b)
(sum * **)
it shows incremental buildup of methods, shows off multi-methods, the
natural calling style, the use of standard lisp types as classes.
Demoing meta-objects is hard, you do that by showing how you can run
Loops & Flavors &etc code; but that really fits in that meta-objects are
mainly there for the system programmers who want to do things like use
object-oriented programming to either do backward compatibility things
or to implement new kinds of reasoning systems or otherwise hack the
system. Its important to put it in the standard because we think that it
allows what was otherwise going to be a divergence in the community sit
on a common base, and allows for future growth.
re "methodologies for object-oriented programming", that's an awfully
big word for someone who wants simplicity. This is just another way of
writing functions & structures; , the methodology is pretty much the
same. You can make it lots more complicated than that and invent all
kinds of methodologies and papers and strategies, but you can also do
without 'em, just as we've done for Lisp.
∂06-Nov-86 1227 Kahn.pa@Xerox.COM Re: discussion wanted
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Nov 86 12:27:48 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 06 NOV 86 11:56:37 PST
Date: 6 Nov 86 11:56 PST
Sender: Kahn.pa@Xerox.COM
Subject: Re: discussion wanted
In-reply-to: Masinter.pa's message of 6 Nov 86 04:23 PST
To: Masinter.pa@Xerox.COM
cc: hpfclp!robert@hplabs.HP.COM,
common-lisp-object-system@sail.stanford.edu
From: Ken Kahn <Kahn.pa@Xerox.COM>
Message-ID: <861106-115637-1190@Xerox>
I like your answer and your "user model" and examples. The only
disagreement I have is with
re "methodologies for object-oriented programming", that's an
awfully big word for someone who wants simplicity. This is just
another way of writing functions & structures; , the methodology is
pretty much the same. You can make it lots more complicated than
that and invent all kinds of methodologies and papers and
strategies, but you can also do without 'em, just as we've done for
Lisp.
I think there are lots of methodology issues that come up that most Lisp
programmers are not familiar with. Just as an example, consider the
issue of whether to subclass vs adding more slots to a class. One would
like to present a methodology that says that if the subclasses differ
from the super in only trivial ways then it probably was a mistake to
make those subclasses. E.g.
(defclass ball (color ...) ...)
vs
(defclass ball ...)
(defclass red-ball ... (ball))
(defclass green-ball ... (ball))
...
I think this is just the tip of the iceberg.
∂06-Nov-86 1700 masinter.PA@Xerox.COM Re: discussion wanted
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Nov 86 17:00:13 PST
Received: from Chardonnay.ms by ArpaGateway.ms ; 06 NOV 86 15:30:02 PST
From: masinter.PA@Xerox.COM
Date: 6 Nov 86 15:28:51 PST
Subject: Re: discussion wanted
In-reply-to: Kahn's message of 6 Nov 86 11:56 PST
To: Kahn.PA@Xerox.COM
cc: Masinter.PA@Xerox.COM, hpfclp!robert@hplabs.HP.COM,
common-lisp-object-system@sail.stanford.edu
Message-ID: <861106-153002-1463@Xerox>
Sorry, I think I typed too fast. I agree there are lots of methodology
issues. I just don't think there are a lot more *new* methodology issues
in Common Lisp + objects as there aready in Common Lisp without objects.
Your example is as true for structures as it is for classes. People
programming in Interlisp have always gone back and forth over how to lay
out records, whether something new should be a new record, etc. too.
This is an issue in Pascal or Mesa or Modula, about whether you define
new types or overload old ones, etc.
∂08-Nov-86 1319 RPG Clarification
To: common-lisp-object-system@SAIL.STANFORD.EDU
Regarding DEFCLASS, did we really decide that there were two ways to
specify default values for a slot?
(deflcass foo (baz)
(random-slot 3)
(another-random-slot :default-value 3))
I'm sure we can find a millionsusers who want one and another million
who want the other, and I'm sure the simple case is useful in simple cases
and the verbose case in verbose cases, but do we really need to complicate
the thing specification with multiple ways of doing the same thing?
Regarding DEF-GENERIC-OPTIONS, did we agree to include INTERFACE and
METHOD-ARGUMENTS? It seems that this is excessive generality. I presume
one can accomplish all of this with meta-objects (GENERIC-FUNCTION-CLASS
and METHOD-CLASS). Do we need 2 ways to do this?
-rpg-
∂08-Nov-86 1442 kempf%hplabsc@hplabs.HP.COM Re: Clarification
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 8 Nov 86 14:41:56 PST
Received: from hplabsc by hplabs.HP.COM ; Sat, 8 Nov 86 14:38:36 pst
Received: by hplabsc ; Sat, 8 Nov 86 14:38:38 pst
Date: Sat, 8 Nov 86 14:38:38 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8611082238.AA29539@hplabsc>
To: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Clarification
>Regarding DEF-GENERIC-OPTIONS, did we agree to include INTERFACE and
>METHOD-ARGUMENTS? It seems that this is excessive generality. I presume
>one can accomplish all of this with meta-objects (GENERIC-FUNCTION-CLASS
>and METHOD-CLASS). Do we need 2 ways to do this?
I agree. This functionality would probably be best left to the meta-object
protocol.
Jim Kempf kempf@hplabs
∂09-Nov-86 1900 Moon@STONY-BROOK.SCRC.Symbolics.COM Clarification
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Nov 86 19:00:14 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 154097; Sun 9-Nov-86 21:58:46 EST
Date: Sun, 9 Nov 86 21:58 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Clarification
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 8 Nov 86 16:19 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861109215812.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 08 Nov 86 1319 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Regarding DEFCLASS, did we really decide that there were two ways to
specify default values for a slot?
(deflcass foo (baz)
(random-slot 3)
(another-random-slot :default-value 3))
I'm sure we can find a million users who want one and another million
who want the other, and I'm sure the simple case is useful in simple cases
and the verbose case in verbose cases, but do we really need to complicate
the thing specification with multiple ways of doing the same thing?
We did decide to do this, according to my notes. The design rationale
was to make it possible to have slot options without specifying an
initial value, and at the same time to have an initial value without
having to resort to the more complex syntax of slot options.
If you want to re-open the issue, you should propose a specific alternative.
By the way, if we've decided to cut the specification down to something
simple, because it's too big and complicated looking, I have a lot of
suggestions! However, I think Masinter made a fairly good case for it
not being quite as complicated as it looks.
Regarding DEF-GENERIC-OPTIONS, did we agree to include INTERFACE and
METHOD-ARGUMENTS? It seems that this is excessive generality. I presume
one can accomplish all of this with meta-objects (GENERIC-FUNCTION-CLASS
and METHOD-CLASS). Do we need 2 ways to do this?
This is still being discussed. Obviously anything can be done with
meta-objects, so the fact that something can be done with meta-objects
cannot be grounds for not providing any other way to do it, or the
standard would consist of nothing but meta-objects. The real basis for
deciding whether or not to put something into the programmer interface
is whether or not it will be heavily used by the type of programmers who
should not need to resort to meta-objects.
∂10-Nov-86 1003 Gregor.pa@Xerox.COM Re: Clarification
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Nov 86 10:03:45 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 10 NOV 86 09:58:11 PST
Date: 10 Nov 86 09:58 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Clarification
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sun, 9 Nov 86 21:58 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861110-095811-1075@Xerox>
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Regarding DEFCLASS, did we really decide that there
were two ways to specify default values for a slot?
We did decide to do this, according to my notes. The design
rationale was to make it possible to have slot options without
specifying an initial value, and at the same time to have an
initial value without having to resort to the more complex syntax
of slot options.
If you want to re-open the issue, you should propose a specific
alternative.
I remember us deciding this too. But I don't remember us saying
explicitly that attempting to access a slot, whose value has not yet
been set (initialized) signalled an error. Unless we specify that
accessing a slot whose value has not yet been initialized is an error, I
don't see that it is necessary to have a syntax which allows the use of
options without specifying an initial value.
To go even further, I don't see that having unitialized slots signal an
error is necessary, so I would propose the following syntax for slots in
defclass:
(defclass foo ()
slot-1 ;just slot name is legal
(slot-2 nil) ;or name and default value
(slot-3 nil :accessor bazola)) ;or name, default and options
∂10-Nov-86 1224 Bobrow.pa@Xerox.COM Re: Clarification
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Nov 86 12:23:48 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 10 NOV 86 11:36:50 PST
Date: 10 Nov 86 11:33 PST
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Clarification
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 08 Nov 86
13:19 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861110-113650-1243@Xerox>
Regarding DEFCLASS, did we really decide that there were
two ways to specify default values for a slot?
(defclass foo ()((baz) (random-slot 3) (another-random-slot
:default-value 3))
My memory is that we didn't discuss this. The issue seems to me whether
we should be able to specify a slot without specifying an initial value.
I spoke to Steele about this, and he felt that was a gap. There are
two arguments for this
1) there may be some cost to initializing storage that will always be
stored in first before access. Question, is this significant? I thought
the Flavors trick of BLTing a dummy instance full of storage.
2) More important specifying an initial value when none is intended
could be misleading or wrong e.g. if :type is specified does the user
have to provide some form that evaluates to that kind. This could be
hard if the type is not yet defined (or if it is hard to cons up one, or
if storing one could cause other side effects). But we have not yet
agreed to support :type. I think we ought to at least allow it.
If we accept this, then what is the meaning of a slot description with
(baz) or just baz. Are these legal? The first I guess must mean no
default value, the second ???
An alternative syntax is to provide a special symbol e.g.
:no-default-value that means , and insist the user type that in. This
simplifies the common case of extending the slot description from
(baz (baz-form)) to
(baz (baz-form) :accessor zed) '
rather than having to insert :default-value.
-- danny
∂10-Nov-86 1301 Bobrow.pa@Xerox.COM Re: Clarification
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Nov 86 13:01:48 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 10 NOV 86 12:48:41 PST
Date: 10 Nov 86 12:48 PST
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Clarification
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 08 Nov 86
13:19 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861110-124841-1370@Xerox>
Regarding DEF-GENERIC-OPTIONS, did we agree to include
INTERFACE and METHOD-ARGUMENTS? It seems that this is excessive
generality. I presume one can accomplish all of this with
meta-objects (GENERIC-FUNCTION-CLASS and METHOD-CLASS). Do we need
2 ways to do this?
I agree that this would be easily done in the metaobject protocol. The
ease of writing code there would be enhanced by the kind of
functionality (functions and macros) I suggested in my simplified
version of define-method-combination. I have seen no comments on my
last proposal (message of Oct 20). Dave, what is your reaction?
-- danny
∂10-Nov-86 1801 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Clarification
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 10 Nov 86 17:51:39 PST
Received: from ti-csl by csnet-relay.csnet id bt14349; 10 Nov 86 19:45 EST
Received: from Jenner (jenner.ARPA) by tilde id AA04705; Mon, 10 Nov 86 16:55:23 cst
To: Gregor Kiczales <Gregor.pa@XEROX.COM>
Cc: common-lisp-object-system@SU-AI.ARPA
Subject: Re: Clarification
Date: 10-Nov-86 16:50:44
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2741035841@Jenner>
I remember us deciding this too. But I don't remember us saying
explicitly that attempting to access a slot, whose value has not yet
been set (initialized) signalled an error. Unless we specify that
accessing a slot whose value has not yet been initialized is an error, I
don't see that it is necessary to have a syntax which allows the use of
options without specifying an initial value.
To go even further, I don't see that having unitialized slots signal an
error is necessary, so I would propose the following syntax for slots in
defclass:
(defclass foo ()
slot-1 ;just slot name is legal
(slot-2 nil) ;or name and default value
(slot-3 nil :accessor bazola)) ;or name, default and options
The problem with that reasoning is the initial values can come from
some other source: like make-instance or being set in a method (written,
not necessary read).
(defclass foo ()
(slot-1 :accessor foo-1))
(make-instance 'foo :slot-1 1) should be legal,
and that too:
(setf ob (make-instance 'foo)
(foo-1 ob 1)
The accessor option makes sense even without any default value.
I think we should keep the two ways to provide a default value, it's
not that heavy in the implementation, or documentation and reduces
user frustration.
Patrick.
∂11-Nov-86 1132 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Draft Comments Part II
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 11 Nov 86 11:32:45 PST
Received: from ti-csl by csnet-relay.csnet id ak04751; 11 Nov 86 13:27 EST
Received: from Jenner (jenner.ARPA) by tilde id AA16521; Tue, 11 Nov 86 09:47:16 cst
To: common-lisp-object-system@SU-AI.ARPA
Cc:
Subject: Draft Comments Part II
Date: 11-Nov-86 09:41:56
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2741096514@Jenner>
Page 2-26,Documentation:
The text seems to imply that the doc-type argument is meaningless
when the first argument is an object, a generic-function
a class object or a method. Should it be optional then?
Page 2-27, Function-parameters:
If default values and supplied-p arguments are removed,
do the &aux args make sense in there or should they be removed as well?
What does (Function-parameters 'foo ) returns?
(Where foo is (defun foo (a n &key ((:start first-index))) ...))
The text should specify what happens when someone uses SETF
with FUNCTION-PARAMETERS (I am not sure what it means anyway).
Page 2-28, generic-function-method-combination
I think the text should say method-combination-type instead of
method-combination.
Page 2-30, Get-method, 2-37 remove-method
The specializers argument should be consistent between those functions.
If the number of specializers is greater than what the generic function
defines, should an error be signalled? (I would say yes).
There are some terminology inconsistencies throughout the document:
Built-in Class is used for Standard-Type-Class.
Dispatch and Method Selection are used in different places (Concept
and glossary).
One thing that needs to be decided for the document to be consistent
is what a method is, quoting RPG,
"Methods are objects with, possibly, some internal structure - this has not
yet, I believe, been decided. Methods include a function, called the
`method function,' and possibly some other user-visible information. One
such possible part of the internal structure might be a pointer back to
the generic function of which the method is part. The term `method' is
commonly used to refer to method objects."
Right now the document is very vague about methods. get-method return a method-object
but the only function in the document that will accept method object is DOCUMENTATION.
If they are first class objects, then we must be able to get some information out of them
(arglist, qualifier, function...).
Patrick.
∂11-Nov-86 1311 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Method combination -- writeup for revised syntax
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 11 Nov 86 13:10:43 PST
Received: from ti-csl by csnet-relay.csnet id aa05418; 11 Nov 86 14:35 EST
Received: from Jenner (jenner.ARPA) by tilde id AA22690; Tue, 11 Nov 86 12:20:38 cst
To: Danny Bobrow <Bobrow.pa@XEROX.COM>
Cc: Moon@SCRC-STONY-BROOK.ARPA, common-lisp-object-system@SU-AI.ARPA
Subject: Re: Method combination -- writeup for revised syntax
Date: 11-Nov-86 12:15:08
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2741105702@Jenner>
Danny,
If I read your new proposal correctly, the only significant differences
you have with what Moon proposes are:
- FIND-ALL-METHODS replaces the method-selection part of DEFINE-METHOD-COMBINATION.
As I see it, it still does not solve the point raised by Moon
about signalling an error if there are extra methods that have not
been matched.
- The filter language of FIND-ALL-METHODS. This language can be integrated into
the method-selection option of Moon's DEFINE-METHOD-COMBINATION.
- Having a SORT-METHODS that can merge several method lists. This one can be useful.
I would be in flavor of keeping Moon's proposal, integrating the filter language
in the method-selection is somebody convinces me that it should be included, and
add the SORT-METHODS function.
PS. Has anybody thought about my proposal for method combination selection?
Patrick.
∂12-Nov-86 0811 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Draft Comments Part I
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 12 Nov 86 08:10:51 PST
Received: from ti-csl by csnet-relay.csnet id aa18603; 12 Nov 86 10:24 EST
Received: from Jenner (jenner.ARPA) by tilde id AA17196; Wed, 12 Nov 86 07:23:07 cst
To: Dick Gabriel <RPG@SU-AI.ARPA>
Cc: common-lisp-object-system@SU-AI.ARPA
Subject: Draft Comments Part I
Date: 12-Nov-86 07:16:51
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2741174208@Jenner>
------------------
RETURN-PATH: <>
TO: DUSSUD@Jenner
DATE: 9-Nov-86 14:50:57
FROM: Mailer@Jenner
MESSAGE-ID: <Mailer.2740942256@Jenner>
Mail not sent to the following people:
common-lisp-object-system@su-ai.arpa
Dick Gabriel <RPG@su-ai.arpa>
Because: The OPEN operation timed out before the connection became ESTABLISHED
Retrying until 11/12/86 14:31:45
TO: Dick Gabriel <RPG@su-ai.arpa>
CC: common-lisp-object-system@su-ai.arpa
SUBJECT: Draft Comments Part I
DATE: 7-Nov-86 14:31:48
FROM: DUSSUD@Jenner
MESSAGE-ID: <DUSSUD.2740768305@Jenner>
Here are some comments about the TEX files that Linda sent me:
Pages 1-6 and 1-19, structure-class is mentioned, I was under the
impression that we agreed to subsume the type-producing version
of DEFSTRUCT under the regular defclass mechanism. It will happen that
DEFSTRUCT will produce classes having at most one class-component
but I don't see a need for a separate metaclass.
I have trouble understanding the rationale for the type/class
diagram on page 1-7. If it says that the user can rely on it to
define methods, I think it's not quite right.
Some types listed as separate can be collapsed together (long-float
and double-float).
Method Selection and Method Combination is placed before Class Precedence
even though method combination makes use of the Class Precedence List concept.
From the Basic User Interface Functions:
Page 2-15: "this is the same behavior as a DEFVAR with no initial value form"
I don't think so, DEFVAR with no value merely proclaims the variable to be
special. The variable can be bound before the DEFVAR evaluation and if so the user is
free to reference it. In the case of an instance slot, we know that it was
never initialized before.
Page 2-18: "the new generic function object is returned as the results"
It seems inconsistent with the rest of DEF... which return the name of their
objects. Also, I found "If a DEFGENERIC form is evaluated when a generic function
of the same name is already defined, the new definition replaces the old one",
which is (or isn't?) different from "The existing generic-function object is modified"
found in page 1-8.
More later...
Patrick.
------------------
∂12-Nov-86 0820 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Draft Comments
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 12 Nov 86 08:19:54 PST
Received: from ti-csl by csnet-relay.csnet id ab18603; 12 Nov 86 10:27 EST
Received: from Jenner (jenner.ARPA) by tilde id AA17274; Wed, 12 Nov 86 07:24:20 cst
To: Dick Gabriel <RPG@SU-AI.ARPA>
Cc: common-lisp-object-system@SU-AI.ARPA
Subject: Draft Comments
Date: 12-Nov-86 07:18:06
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2741174284@Jenner>
------------------
RETURN-PATH: <>
TO: DUSSUD@Jenner
DATE: 9-Nov-86 16:23:50
FROM: Mailer@Jenner
MESSAGE-ID: <Mailer.2740947829@Jenner>
Mail not sent to the following people:
common-lisp-object-system@su-ai.arpa
Dick Gabriel <RPG@su-ai.arpa>
Because: The OPEN operation timed out before the connection became ESTABLISHED
Retrying until 11/12/86 16:11:37
TO: Dick Gabriel <RPG@su-ai.arpa>
CC: common-lisp-object-system@su-ai.arpa
SUBJECT: Draft Comments
DATE: 7-Nov-86 16:11:40
FROM: DUSSUD@Jenner
MESSAGE-ID: <DUSSUD.2740774297@Jenner>
There is an inconsistency between the Concept and Design Rationale
sections concerning built-in classes:
In the Design Rationale section, there is a bunch of CL types
that don't have any associated class. In the Concept section,
only Atom and Common don't have associated class.
Patrick.
------------------
∂12-Nov-86 1225 Moon@ALDERAAN.SCRC.Symbolics.COM Comments on the function chapter
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 12 Nov 86 12:25:27 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 19674; Wed 12-Nov-86 15:23:12 EST
Date: Wed, 12 Nov 86 15:23 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Comments on the function chapter
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861112152312.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
I haven't gone carefully through the Concepts chapter yet, but here is the
first installment of my comments on the 30 October version of the Functions
chapter (which seems to be the most recent version).
GENERAL COMMENTS:
The term "user interface" is used all over, yet the proposed standard does
not in any way specify a user interface. A user interface is something for
end-users, typically involving display screens, keyboards, etc. The title
should be changed to "programmer interface".
-------
This spec throws a bewildering variety of functions at the reader. I would
like to see a more layered presentation. There are two ways to do this;
one is to have a separate alphabetized dictionary of functions for each
layer. The other is to have an introductory section organized by layers,
containing one-line descriptions of the functions in each layer, followed
by a single alphabetized dictionary of everything. I don't care which we
do, but I don't think the Concepts chapter can substitute for that
introductory section. I suggest the following four layers:
(1) Basic programming language facilities that all programmers need to understand
(2) Define-method-combination and its support functions
(3) Primitive functions that implement the macros in (1) and can be used to build tools
(4) Meta-objects
Some might argue that this type of layered presentation is only necessary
in a user manual and not in a standards specification. I don't believe
that. Anything we can do to make it easier for the X3J13 committee and
others to understand this proposed standards specification will be to the
good.
I would categorize the existing functions in the Functions chapter as follows:
(1) call-next-method, change-class, defclass, defgeneric, defgeneric-setf,
defmethod, defmethod-setf, describe, make-instance, print-object,
with-slots
(2) define-method-combination
(3) add-method, class-of(*), documentation, get-method(+),
lambda-list-specializers(+), make-generic-function, remove-class,
remove-method, remove-setf-method, slot-value(*)
(4) argument-precedence-order, function-parameters,
generic-function-method-combination, generic-function-p
(*) means maybe this belongs in category 1 instead
(+) means maybe this belongs in category 4 instead
-------
A format needs to be designed for documenting specializable generic
functions (that is, functions that are already defined for which the
programmer is expected to define methods). The current descriptions of
these functions (describe, print-object, and possibly change-class) does
not work very well, because they don't fit the function-description format
being used.
-------
Several functions (add-method, get-method, remove-method) take an argument
that is a generic-function or the name of a generic-function. We have to
decide how to deal with the not obviously named generic-functions involved
with defmethod-setf and defgeneric-setf. We discussed this around 21 Oct
and there didn't seem to be total agreement, but my reading is that we have
to do two things:
(1) There is a new function get-setf-generic-function, which takes as its
argument a generic function or the name of a function, and returns the
associated setf-generic-function.
(2) The functions that accept the name of a generic function also accept
a list (SETF f), where f is the name of a function; this is a synonym for
(get-setf-generic-function f). Note well: f doesn't have to be a generic
function, it can be an ordinary function.
My reading is that we can't do the third thing discussed then, which was to
make Common Lisp standardize more of the insides of setf.
None of this would be necessary if Common Lisp had function-specs (see any
Zetalisp manual), but since it doesn't, we have to do something.
We need to hear from RPG about whether this is consistent with his
anonymous generic function ideas, or would somehow preclude them.
-------
Several functions (add-method, get-method, remove-method) use the phrase
"the qualifiers argument specifies the method combination options". I
don't believe this is correct terminology. The word "options" should
certainly not be used, and the way this is phrased would make the reader
think that this is the same thing as the :method-combination clause of
defgeneric.
Instead it should say "The qualifiers argument is a possibly-empty list of
method qualifiers" and cross-reference to the section explaining what
method qualifiers are (right now this is only a brief paragraph on
page 1-8).
-------
Several functions (add-method, get-method, lambda-list-specializers,
remove-method) refer to lists of argument specializers. An easy problem
is the reference to giving lists of argument specializers to defmethod;
defmethod doesn't take any such argument. Another easy problem is
that these are called parameter specializers, not argument specializers;
see the defmethod writeup.
More difficult is that I can't find any definition of what is in these
lists. Three issues:
(1) Is an argument specializer, as seen at this level, a class object
or a Common Lisp type specifier?
(2) How are the various specializers combined into a list? Don't overlook
the possibility of future extention to specialization of keyword arguments.
Quite a long time ago I made a proposal about this, but I don't know what
its status is; we haven't discussed it recently. Briefly, the proposal
was that a method's list of argument specializers would take the form
((pos type) ...)
where pos is one of:
a non-negative integer, for required and optional arguments
a symbol, for keyword arguments
something else, for &rest arguments, if it made sense to specialize them
Furthermore the list would be sorted into a canonical order, with the
positional arguments in numerical order followed by the keyword arguments
in alphabetical order [need some resolution of identically named symbols
in different packages].
(3) Are unspecialized argument specializers (i.e. the symbol T) removed
from the list?
-------
TYPEP and TYPE-OF need to be mentioned in the Functions chapter, since
their CLtL behavior is modified by the proposal. Each writeup for a
function that is already defined by Common Lisp should note that fact
in its remarks field (or in a special field employed for this purpose).
-------
I don't like the use of a single italicized word to stand for a pair
of list elements (as in defclass and with-slots). This is standard
practice in BNF, but in Lisp it makes it all too easy for the reader
to get confused about where the parentheses go. I looked through CLtL
and could not find any instances of this practice. Unless CLtL uses
this practice, I think we should avoid it.
-------
COMMENTS ON SPECIFIC FUNCTIONS:
This will have to wait for another day. I'm out of time, and this message
is already pretty long.
∂12-Nov-86 1256 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Next Step
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 12 Nov 86 12:54:59 PST
Received: from ti-csl by csnet-relay.csnet id ah21201; 12 Nov 86 14:59 EST
Received: from Jenner (jenner.ARPA) by tilde id AA17062; Wed, 12 Nov 86 07:21:35 cst
To: Dick Gabriel <RPG@SU-AI.ARPA>
Cc: common-lisp-object-system@SU-AI.ARPA
Subject: Re: Next Step
Date: 12-Nov-86 07:15:17
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2741174113@Jenner>
------------------
I apologize I you get this message twice, we had trouble getting to Arpanet.
TO: Dick Gabriel <RPG@su-ai.arpa>
CC: common-lisp-object-system@su-ai.arpa
SUBJECT: Re: Next Step
DATE: 7-Nov-86 13:53:10
FROM: DUSSUD@Jenner
MESSAGE-ID: <DUSSUD.2740765987@Jenner>
Because it appears that FUNCTION.TEX is essentially stable and because the
deadline for sending it to X3J13 approaches, Linda and I are going to
start going over it to
1. make it read like a specification (dull but precise);
2. make sure exactly the decisions we reached are discussed; and
3. turn it into TEX.
If there are major comments about the contents of FUNCTION.TEX,
you should send them soon.
-rpg-
Dick,
Basically, I agree with Moon concerning the sending of the
draft to X3J13. I guess the message we got from Robert Heckendorn is
typical of what's waiting for us if we send something which is not
complete and/or not completely agreed upon.
The Common Loops presentation given by Danny at the last
meeting is close enough to what has been defined/agreed upon so far.
We wouldn't bring that much to the X3J13 members.
I guess if any preparation needs to be done for December 10,
it should be towards getting intelligent replies to concerns
such as those Robert Heckendorn has.
Patrick.
P.S Are we going to meet again in Dallas?
------------------
∂12-Nov-86 2241 @MC.LCS.MIT.EDU:MOON%ML.AI.MIT.EDU@MC.LCS.MIT.EDU Second installment of comments on Functions chapter
Received: from MC.LCS.MIT.EDU by SAIL.STANFORD.EDU with TCP; 12 Nov 86 22:40:58 PST
Received: from ML.AI.MIT.EDU by MC.LCS.MIT.EDU via Chaosnet; 13 NOV 86 01:42:52 EST
Date: Thu, 13 Nov 86 01:40:21 EST
From: "David A. Moon" <MOON%ML.AI.MIT.EDU@MC.LCS.MIT.EDU>
Subject: Second installment of comments on Functions chapter
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <[ML.AI.MIT.EDU].1835.861113.MOON>
I'm omitting all comments on TeX errors, formatting, and vestiges of
previous versions that weren't deleted. I comment on a few typos that
might be easy to miss, but otherwise concentrate on content issues.
ADD-METHOD:
Doesn't say whether the result ("the modified generic function")
is the same generic function that was supplied as an argument,
or is a freshly-created generic function object that is similar
to the argument but has a method added to it. I believe the answer
is that it is the same object. Fix this in both "purposes" and
"values".
The function argument is not described. What are the requirements on this
function as to what arguments it receives, what values it returns, what
dynamic environment it runs in, what it can do, etc.? I would like
implementations to be free to have different argument lists on their method
functions than the arguments of the generic function; this permits some
important optimizations. There are also requirements for CALL-NEXT-METHOD.
The best way, I think, would be to require that the function argument to
add-method be a function that has been transformed by a method on the
generic function before being compiled.
ARGUMENT-PRECEDENCE-ORDER:
I don't understand why this function exists. Is it just for completeness,
so that all slots of a generic-function object have accessors?
CHANGE-CLASS:
In the first line, "the new class" should be "a new class".
The instance argument should not be required to have a metaclass of
class, since other metaclasses might also support change-class.
This is really trying to say that not all metaclasses support
change-class, but the metaclass you get by default is required to
support it.
Can the new-class argument be the name of a class?
We discussed (in Menlo Park) restrictions on when change-class can
be called; they need to go into the document.
Is change-class a generic function that can be specialized by the user?
CLASS-OF:
Values field missing, it's a class object (stress not a class name).
The first sentence of Remarks is misleading since make-instance allows the
name of a class as its class argument. It also would not be true in
systems, such as Flavors, that have an extension such that make-instance
can be given a more general class and then instantiate a more specific
class chosen according to the init options specified. This whole sentence
is pretty useless, actually. It's trying to be a definition of "most
specific class" which is pretty hard to define if it isn't self-explanatory.
DEFCLASS:
I think some or all of the :allocation options are complex and unnecessary
and should be removed. Certainly :dynamic and :none should go away.
(:instantiable nil) is kind of a double negative. In general, options that
are turned on by default are confusing. I think it would be better to use
a positive wording, e.g. :abstract, so it can be off by default. Actually
the same arguments for eliminating :required-methods apply to this option.
We didn't discuss or agree on :predicate. It seems to me that typep serves
this function adequately, since the class and type systems are integrated.
If a class with the specified name is already defined, does this make a new
class object, or modify the existing one? I think it should modify.
Is it really true that a slot-name can be any non-null symbol? Because
of with-slots, I think the real restriction is that a slot-name must be
a symbol that is legal to use as a variable. For instance, keywords would
be illegal. Opinions?
Is the note under :allocation :class saying that a local slot description
completely overrides an inherited one really true? This would imply that
you could turn off :default-value or :accessor by giving another slot
description without those options, and I think in Menlo Park we decided
against this. Perhaps the note applies only to :allocation?
The description of :reader says non-null-symbol in a couple of places
where it means to say generic-function-name.
With :accessor-prefix and :reader-prefix, how does one specify that the
accessor name is to be the same as the slot name? A prefix of "" won't
work, since that re-interns the accessor name in the current package. Do
we need two more options for this? Should we treat the symbol NIL as a
special case? I think two more options would be more tasteful.
The description of :constructor will have to be expanded when we
finalize the initialization protocol. Actually, :constructor is
only an efficiency optimization, so it could be removed from the
standard and people could just write functions that call make-instance.
I believe :initable-slots should be marked "still under discussion."
The Values field says the name of the class is returned but the Purpose
field four pages earlier says the class object is returned. Returning
the object is more consistent with other functions.
In Remarks: "argument specifier" -> "parameter specializer". When it says
a class can override an inherited option, "override" needs to be defined
more precisely; some of the options are additive, others truly override.
DEFGENERIC:
Purpose field: in "symbol function cell of the symbol", don't say "symbol"
twice. If the symbol already has a function definition, what happens?
I think the answer is if the definition is a generic function, it is
modified (rather than replaced with a new generic function object).
The second paragraph of the Remarks field seems to contradict this,
but I believe that was not our intent. If a new generic-function object
is made, does it receive the methods of the old generic-function or
does it start life with no methods?
If the prior definition is an ordinary function, is it turned into a
default method or discarded?
The syntax of :argument-precedence-order is described but not what it does.
Just say that arguments are considered in the order listed, or words to
that effect.
The discussion of declare is self-contradictory. I would rewrite the whole
paragraph as follows:
(declare declaration+) Declarations that could appear at the beginning of
the body of a defun with the same name and lambda-list are permitted. Type
declarations of the parameters are used by some Common Lisp implementations
when compiling calls to the generic function. The optimize declaration can
be used to control whether method selection is optimized for speed or for
space. An implementation should treat any declaration it does not
recognize the same as it would if it appeared in defun (see Common Lisp the
Language page 161). Declarations in defgeneric are not automatically
incorporated into the bodies of methods.
DEFGENERIC-SETF:
Note that the first subform does not have to be a generic function name.
It can be an ordinary function name.
DEFMETHOD:
If a method for the same generic function, with the same qualifiers
and specializers, already exists, does defmethod update the existing
method object or create a new one? I think it should update.
DEFMETHOD-SETF:
Same comments as in defgeneric-setf and defmethod.
DOCUMENTATION:
This seems to be unsure whether it is the Common Lisp documentation
function, which takes two arguments that together are the name of
an entity, or the Zetalisp documentation function, which takes one
argument. Is the intent to allow documentation to be applied to
meta-objects as well as to names? Some systems do not store the
documentation strings inside the objects, but instead associate
them with the names, so that doesn't seem to fit. I suggest refraining
from extending this function beyond Common Lisp. The issue here is
that Common Lisp doesn't have function-specs, so methods can't have names.
There is no problem with classes, generic functions, and method-combination
types.
FUNCTION-PARAMETERS:
I don't understand what relation this has to object-oriented programming.
I think it should be removed from this proposal.
GENERIC-FUNCTION-METHOD-COMBINATION:
I don't understand what the value returned by this is. Is it the
cdr of a :method-combination defgeneric clause? Also I don't think
this function is needed, except at the meta-object level.
GENERIC-FUNCTION-P:
This function is unnecessary, use TYPEP.
GET-METHOD:
What happens if a function whose name is given by the first argument
exists, but it is not generic? Does this return NIL or signal an error?
LAMBDA-LIST-SPECIALIZERS:
I don't understand why this function needs to be documented.
MAKE-GENERIC-FUNCTION:
This has a lot of little inconsistencies with defgeneric. It's not clear
which arguments are required and which are optional. This is best settled
after defgeneric has stabilized.
PRINT-OBJECT:
The writeup is just some mail I sent and needs to be translated into English
and probably to be shortened.
REMOVE-SETF-METHOD:
This should not exist, since there is no add-setf-method nor get-setf-method.
SLOT-VALUE:
This mentions the read-only slot feature, which has been removed.
What happens if there is no slot with the given name?
I think it should signal an error.
Do primitive (aka built-in) (aka standard-type) objects have slots?
I think there should be no slots defined by the standard, but the
possibility of implementation-defined slots should be allowed.
Do defstructs have slots that slot-value can access?
I can't figure out what I think.
WITH-SLOTS:
Is the first subform really allowed to be empty? I.e. (with-slots () body...)
The :prefix option needs to describe interning in the current package,
same as in the :accessor-prefix option of defclass.
The make-horizontal example should be modified to reflect the fact
that the instance can be any expression, not just a variable. Remove
the let.
The second paragraph under Remarks is a bit mixed up. The first sentence
should say "signals an error." The second sentence is probably not
about inferring the class at all; I think what this really means to say
is that with-slots signals an error if two of the pseudo-variables have
the same name. This can happen when more than one instance clause is
given, and can also happen with one instance when :prefix is given and
there are two slot names with the same name but in different packages..
∂13-Nov-86 1217 RPG ARGUMENT-PRECEDENCE-ORDER
To: common-lisp-object-system@SAIL.STANFORD.EDU
I presume this and the other facet accessors for generic functions are
here because they are SETFable. If they are not SETFable, then possibly
they don't need to be in the specification. Also, if these facets are not
SETFable, then any anonymous generic function facility will be
extraordinarily ugly.
FUNCTION-PARAMETERS is possibly included due to an oversight.
-rpg-
∂13-Nov-86 1438 Moon@STONY-BROOK.SCRC.Symbolics.COM ARGUMENT-PRECEDENCE-ORDER
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 13 Nov 86 14:37:53 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 158819; Thu 13-Nov-86 15:34:20 EST
Date: Thu, 13 Nov 86 15:33 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: ARGUMENT-PRECEDENCE-ORDER
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 13 Nov 86 15:17 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861113153339.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 13 Nov 86 1217 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
I presume this and the other facet accessors for generic functions are
here because they are SETFable. If they are not SETFable, then possibly
they don't need to be in the specification. Also, if these facets are not
SETFable, then any anonymous generic function facility will be
extraordinarily ugly.
That's a good point. Either these should be SETFable, or
MAKE-GENERIC-FUNCTION should accept a keyword argument that is a generic
function to be updated from the other arguments, or there should be a
function MODIFY-GENERIC-FUNCTION which takes a required generic function
argument followed by the same keyword arguments that MAKE-GENERIC-FUNCTION
accepts. I prefer the last of these three alternatives, but any of them
seems acceptable.
∂13-Nov-86 1514 masinter.pa@Xerox.COM Re: ARGUMENT-PRECEDENCE-ORDER
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 13 Nov 86 15:13:51 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 13 NOV 86 15:10:55 PST
Date: 13 Nov 86 15:10 PST
From: masinter.pa@Xerox.COM
Subject: Re: ARGUMENT-PRECEDENCE-ORDER
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 13 Nov 86 15:33 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861113-151055-1494@Xerox>
If the spec just says "there's a class generic-function which has slots
... ... and conc-name "generic-function", then you get
make-generic-function and all of the accessors and the fact that they
are setfable as well.
There's this nice construct we've invented called defclass; it allows
programmers, with a single defclass, to define all kinds of
constructors, accessors, setf methods and the like. It lets you say a
lot of things tersely.
Why can't we use it in the spec, too?
∂14-Nov-86 0047 RPG Altering Generic Functions
To: common-lisp-object-system@SAIL.STANFORD.EDU
It seems there are three proposals for the primitives used for modifying
generic functions. I will refer to the parts of generic functions as
`facets.' Assuming that all of the facets discussed in the current draft
specification are accepted, the modifiable facets are:
argument-precedence-order, generic-function-class, interface,
method-arguments, method-class, and method-combination-type. Here are the
proposals:
1. There is a series of facet accessors, each accessor naming a SETFable
place.
2. There is a function named MODIFY-GENERIC-FUNCTION that takes a required
generic function argument followed by the same keyword arguments that
MAKE-GENERIC-FUNCTION accepts. Furthermore, there is a function, possibly
named GENERIC-FUNCTION-FACETS, that returns six values, one for each
modifiable facet.
3. MAKE-GENERIC-FUNCTION accepts a keyword argument that is a generic
function to be updated from the other arguments. In addition there is
function, possibly named GENERIC-FUNCTION-FACETS, that returns six values,
one for each modifiable facet.
Here are the advantages and disadvantages of each, as I see them.
1. There are six new function names, one for each modifiable facet.
Because these functions simply are accessors to parts of some larger
object, this requires knowing about many function names. Changing the
facets, though, only requires knowing that the accessors are SETFable.
2. One new function is added, but with six keywords to remember. These
keywords are the same as the keywords for MAKE-GENERIC-FUNCTION, so the
additional cognitive overhead is low. There is a new function that returns
six values, and the order of the values will be difficult or impossible to
remember.
3. This option is very much like number 2, but the name of the function is
misleading - one is not making a generic function, one is altering some of
its characteristics.
Contrasting option 1 with options 2 and 3, the choices we face are similar
to those faced earlier with the sequence functions in Common Lisp. The
two basic choices were: a large series of independent functions or a
smaller series with a set of keyword arguments. The Common Lisp designers
chose the keyword route.
The analogy breaks down here because we require a complex informational
function, GENERIC-FUNCTION-FACETS, which is needed to find out the current
facets of a generic function. Without it, it is not possible to modify
programmatically some facets of one generic function to be the same as
those of another.
Therefore, I favor option 1.
Larry Masinter suggsted something interesting. Generic functions could be
defined to be instances of a generic-function class. Therefore, these six
facets are simply `slots' defined by the generic-function class; instances
have these `slots,' and they are naturally SETFable.
-rpg-
∂14-Nov-86 0951 Gregor.pa@Xerox.COM Re: Altering Generic Functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Nov 86 09:50:55 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 14 NOV 86 09:38:39 PST
Date: 14 Nov 86 09:38 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Altering Generic Functions
In-reply-to: Larry Masinter <Masinter.pa@Xerox.com>'s message of 13 Nov
86 15:10 PST
To: Masinter.pa@Xerox.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861114-093839-2174@Xerox>
The original version of the spec I wrote, had defclass forms in it and
said things like: "Generic functions behave as if they were defined by
the following defclass".
The problem with doing things like that of course is that you have to
say explicitly that SETFing one of the accessors not only changes the
value of the slot, but also has the "desired effect" on the generic
function as a whole.
Otherwise, the reader doesn't know whether setf an accessor will do
"what they want" or just make the internal datastructure of the generic
function inconsistent.
Having to make this explicit reflects a common design decision when
defining a class, namely: "should setf of a slot accessor be the
complete interface for changing the value in a slot, or should their be
some higher-level function which is called to change the value in the
slot as well as change any other information that must stay in sync with
that value."
This kind of situation is common enough and important enough that it
should be brought up explicitly in the spec.
∂14-Nov-86 0951 Gregor.pa@Xerox.COM Re: Altering Generic Functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Nov 86 09:51:13 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 14 NOV 86 09:41:15 PST
Date: 14 Nov 86 09:41 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Altering Generic Functions
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 14 Nov 86
00:47 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861114-094115-2179@Xerox>
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Subject: Altering Generic Functions
To: common-lisp-object-system@SAIL.STANFORD.EDU
It seems there are three proposals for the primitives used for
modifying generic functions.
There is also the obvious combination of proposals 1 and 2, call it
proposal 4.
4. There is a series of facet accessors, they are not setfable; there is
a function named modify-generic-function that takes a required generic
function argument followed by the same keyword arguments that
MAKE-GENERIC-FUNCTION accepts.
∂14-Nov-86 0950 MASINTER.PA@Xerox.COM Re: Altering Generic Functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Nov 86 09:50:49 PST
Received: from Chardonnay.ms by ArpaGateway.ms ; 14 NOV 86 08:45:43 PST
From: MASINTER.PA@Xerox.COM
Date: 14 Nov 86 8:44:28 PST
Subject: Re: Altering Generic Functions
In-reply-to: RPG@SAIL.STANFORD.EDU's message of 14 Nov 86 00:47 PST
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861114-084543-2087@Xerox>
Yes, if you are going to vote, I think my suggestion should be listed as
a separate option. Call it option 4. I think you summarized it
adequately, although I will add that whether the facets are SETF-able of
course depends on whether they are declared as such in the class, and
that it is possible to disallow SETFing of one of the facets simply.
I will add in favor of Option 4 that it allows a natural explaination of
how one might build specialized kinds of generic functions.
∂14-Nov-86 1114 masinter.pa@Xerox.COM Re: Altering Generic Functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Nov 86 11:13:48 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 14 NOV 86 10:35:32 PST
Date: 14 Nov 86 10:34 PST
From: masinter.pa@Xerox.COM
Subject: Re: Altering Generic Functions
In-reply-to: Gregor Kiczales <Gregor.pa>'s message of 14 Nov 86 09:38
PST
To: Gregor.pa@Xerox.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861114-103532-2286@Xerox>
Giving a prototypical defclass for generic-function and then saying
"explicitly that SETFing one of the accessors not only changes the value
of the slot, but also has the "desired effect" on the generic function
as a whole. "
is a natural, simple, easy to explain, consistent and unambiguous
interface to generic function objects.
I agree that there is a common design decision of which this is an
instance, and it is not universally true that one always wants to make
"setf of a slot accessor be the complete interface for changing the
value in a slot". The most important consideration in this common design
decision is whether it frequently necessary to SETF several slots
independently before making the object consistent.
An extension to the current spec which would make this design decision
moot in many more cases would be a generic MODIFY operation, briefly:
(modify object :slot value :slot value :slot value ...)
which setfs the respective slots; for those objects which have global
consisitency requirements, the modifications could be done "in parallel"
and the consistency computed at the end.
∂14-Nov-86 1626 Bobrow.pa@Xerox.COM Re: Altering Generic Functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Nov 86 16:25:27 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 14 NOV 86 13:52:48 PST
Date: 14 Nov 86 13:52 PST
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Altering Generic Functions
To: common-lisp-object-system@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861114-135248-2568@Xerox>
Larry said:
An extension to the current spec which would make this design
decision moot in many more cases would be a generic MODIFY
operation, briefly:
(modify object :slot value :slot value :slot value ...)
which setfs the respective slots; for those objects which have
global consisitency requirements, the modifications could be done
"in parallel" and the consistency computed at the end.
I think this is appropriate, though I would like to avoid having
keywords and to use the real slot-names. I propose we also provide the
dual function
(slot-values slot-name1 slot-name2 ...)
which would return, in the order specified, the values of slot-name1
slot-name2 ....
With this, one would not need to define accessors.
If this proposal is not accepted in general, then at least we should
provide a dual for
(modify-generic-funtion generic-function :key1 value :key2 value ...)
that is
(aspects-of-generic-function :key1, :key2 ...)
that returns this set of values.
I this answers a previous objection of having to leearn both a set of
slot names and a set of access funetions.
-- danny
∂14-Nov-86 1746 RPG Altering Things
To: common-lisp-object-system@SAIL.STANFORD.EDU
Larry's comments bring up the issue of how far we want to take the
meta-class concept in this specification. The standard-type-classes have a
different meta-class from those of DEFCLASS. DEFCLASS is somewhat like
DEFSTRUCT in that it defines an instance structure with slots in which
values may be stored.
As Larry points out, generic functions can made instances of a generic
function class whose meta-class directs the creation of `slot accessors
and updators' that modify facets of the precise sort thing that generic
functions happen to be in some implementation.
Thinking of these facets as slots is quaint, in the same way that one can
think of the `mantissa' and `exponent' as slots in a floating-point number.
Of course, with meta-objects this can done. I say this is `quaint' because
it is promulgating a misnomer of sorts, the misnomer of referring to the
subparts of eveything as `slots.'
It is the class of CLASS that defines `slots.' It would be the class of
FLOATING-POINT-CLASS that would define `mantissa' and `exponent.' We would
be taking the terminolgy specific to DEFCLASS-style classes and misapplying
it in talking about floating-point numbers.
We will recommend to X3J13 that they split DEFSTRUCT into DEFCLASS and
DEFRECORD, which makes sense. When we try to think of floating-point
numbers as instances of classes, and when we break floating-point numbers
into mantissas and exponents, we are making the classes into
record-structure-defining objects. Similarly, thinking of generic functions
as objects whose `slots' are SETFable, we are using the DEFCLASS terminology
to impose some record structure on top of generic functions.
Smalltalk takes seriously the approach I'm hinting at, and possibly we
want to take it seriously as well. The simple class CLASS approach we in
fact take is a simplfication of the whole-hog, Smalltalk approach.
-rpg-
∂14-Nov-86 1806 Gregor.pa@Xerox.COM Re: Second installment of comments on Functions chapter
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Nov 86 18:05:43 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 14 NOV 86 17:24:09 PST
Date: 14 Nov 86 17:21 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Second installment of comments on Functions chapter
In-reply-to: "David A. Moon" <MOON%ML.AI.MIT.EDU@MC.LCS.MIT.EDU>'s
message of Thu, 13 Nov 86 01:40:21 EST
To: MOON%ML.AI.MIT.EDU@MC.LCS.MIT.EDU
cc: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861114-172409-2772@Xerox>
Date: Thu, 13 Nov 86 01:40:21 EST
From: "David A. Moon"
ADD-METHOD:
The function argument is not described. What are the
requirements on this function as to what arguments it receives,
what values it returns, what dynamic environment it runs in, what
it can do, etc.? I would like implementations to be free to have
different argument lists on their method functions than the
arguments of the generic function; this permits some important
optimizations.
I don't see that there should be any restrictions on the function
argument other than that it should have an argument list which is
"congruent" with the generic function in the same way that multiple
defmethods must have congruent argument lists.
I don't see any problems with implementing this "looser" restriction on
the function argument in a way that does not incur a performance
penalty.
In addition, Danny and I spent some time talking about add-method today.
We would like to introduce a new function make-method, and change
add-method as follows (please remember that I may make a mistake
transcribing this, or may for some other reason misrepresent Danny's
opinion):
MAKE-METHOD type-specifiers function
makes a method object of class method. Invoking the method will call
function.
Note that methods are funcallable entities in the same way generic
functions are. In particular, it is legal to say:
(funcall (make-method '(symbol) #'(lambda (x) (list 'symbol x))) 'foo)
Also note that there is no accessor for the function "field" of a
method. The function that a method calls when it is invoked is an
immutable property of the method.
ADD-METHOD generic function method
adds the method to the generic function. Otherwise, is like the old
add method.
(defmethod foo ((x plane)) ...) ==>
(add-method (symbol-function 'foo)
#'(method-lambda ((x plane)) ...))
Additionally, we propose a new macro called method-lambda which the user
can use when building methods which are going to be added to the default
kind of generic function. Method-lambda provides a documented way for
the user to cons up methods which have the same kind of performance
optimizations defmethod has.
METHOD-LAMBDA specialized-lambda-list . body
returns a new method object. the correspondence with make-method is:
(make-method '(plane) #'(lambda (p) p)) =
#'(method-lambda ((p plane)) p)
The only difference is that the method created with method-lambda may be
more efficient.
Given method-lambda, defmethod expands into something like:
(defmethod foo ((p plane)) ...)
(add-method (or (symbol-function 'foo)
(make-generic-function))
#'(method-lambda ((p plane)) ...))
Given method-lambda and generic-function-lambda We see no need to
include any of the variants of labels or flet we have been talking
about. It is easy to implement any of them using method-lambda and
generic-function-lambda.
∂14-Nov-86 1816 RPG Remarks on Moon's Comments
To: common-lisp-object-system@SAIL.STANFORD.EDU
On the :allocation options:
I thought we agreed to what was written.
On :instantiable:
Again, I thought we had agreed to what is in there. If we don't like
T as a default, we can name it :uninstantiable. `Abstract' is a word
I would prefer we not use because it seems like a word users would
want to use.
On DEFMETHOD updating:
Because we have not settled precisely what a method object is,
it is difficult to say whether DEFMETHOD should update or replace
with a copy the method object in a generic function.
If GET-METHOD returns something that can be invoked, and if we decide
DEFMETHOD updates, then we'll need a copier for methods objects, otherwise
users will not be able to get a method out of a generic function and know
it will never be side-effected. Possibly we should have a generic
function copier also.
-rpg-
∂14-Nov-86 1906 Bobrow.pa@Xerox.COM Re: Altering Generic Functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Nov 86 19:05:58 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 14 NOV 86 18:17:32 PST
Date: 14 Nov 86 18:17 PST
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Altering Generic Functions
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 14 Nov 86 13:52 PST
To: common-lisp-object-system@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861114-181732-2842@Xerox>
Obvious typos in my previous message
(slot-values slot-name1 slot-name2 ...)
should be
(slot-values object slot-name1 slot-name2 ...)
and
(aspects-of-generic-function :key1, :key2 ...)
should be
(aspects-of-generic-function generic-function :key1, :key2 ...)
-- danny
∂14-Nov-86 1906 Bobrow.pa@Xerox.COM Re: Altering Things
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Nov 86 19:06:23 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 14 NOV 86 18:59:37 PST
Date: 14 Nov 86 18:59 PST
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Altering Things
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 14 Nov 86
17:46 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861114-185937-2865@Xerox>
Thinking of these facets as slots is quaint, in the same way
that one can think of the `mantissa' and `exponent' as slots in a
floating-point number. Of course, with meta-objects this can done.
I say this is `quaint' because it is promulgating a misnomer of
sorts, the misnomer of referring to the subparts of eveything as
`slots.'
Quaintness is not the issue, but there is a serious concern here. It is
often useful to provide users an interface that makes it look as though
there is a "field" of some type in a data structure, because that is a
useful way to think. For example, points may provide a rho, theta
"field" interface, even though the underlying implementation is x,y.
This is usually most useful when these facets can be changed
independently.
This emphaiszes the difference between the user view and the
implementation view, and it is as true of Smalltalk as it is of
CommonLoops. Even with a single underlying implementation of classes,
they provide some pseudo field messages.
So it is important for us to distinguish user and implementation
descriptions in our writeup. Gregor had a comment in the code that wrt
the user view, generic-function acted as if it were defined by a
defclass (but ...). Without the (but ...) it is a fine explanation,
especially if we put ACTED AS in capital letters.
I agree that we will recommend to X3J13 that they split DEFSTRUCT into
DEFCLASS and DEFRECORD. Several people said they would send me their
versions of DEFRECORD so I could put them together for an initial
proposal. Those of you who have them please do respond.
-- danny
∂14-Nov-86 1906 Gregor.pa@Xerox.COM Meeting at X3J13
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Nov 86 19:06:15 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 14 NOV 86 18:58:37 PST
Date: 14 Nov 86 18:58 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Meeting at X3J13
To: common-lisp-object-system@SAIL.STANFORD.EDU
cc: Gregor.pa@Xerox.COM, Bobrow.pa@Xerox.COM
Message-ID: <861114-185837-2864@Xerox>
I think that someone, in some message suggested that we all get together
at X3J13. Danny and I both think that is a good idea.
We propose that we get together the evening of the first day at X3J13.
Comments?
∂14-Nov-86 1906 Bobrow.pa@Xerox.COM Re: Remarks on Moon's Comments
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Nov 86 19:06:09 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 14 NOV 86 18:52:41 PST
Date: 14 Nov 86 18:52 PST
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Remarks on Moon's Comments
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 14 Nov 86
18:16 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861114-185241-2858@Xerox>
On :instantiable:
I prefer :uninstantiable too (I prefer Moon's default, but this name).
Perhaps because it is hard to spell, the feature should be called
:no-instances
COPIERS
I believe we need copiers for both generic-function objects and
method-objects. These are necessary as long as these objects are not
immutable. With these, and the facilities that Gregor and I talked
about
(see Re: Second installment of comments on Functions chapter 14 Nov 86
17:21 PST)
we can define GLABELS and other of my favorite perversities on top of
rather than within the standard (in a library so we get to try them).
-- danny
∂14-Nov-86 2030 Bobrow.pa@Xerox.COM Re: Meeting at X3J13
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Nov 86 20:30:46 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 14 NOV 86 19:07:28 PST
Date: 14 Nov 86 19:06 PST
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Meeting at X3J13
In-reply-to: Gregor Kiczales <Gregor.pa>'s message of 14 Nov 86 18:58
PST
To: Gregor.pa@Xerox.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU, Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861114-190728-2901@Xerox>
To be more specific, we propose getting together at dinner and after on
Wednesday Decmember 10. To be continued on Thursday evening if
desired.
-- danny
∂14-Nov-86 2105 RPG Meeting at X3J13
To: common-lisp-object-system@SAIL.STANFORD.EDU
It's possible for me, but I think that the function cell discussion
will be at the center this meeting.
-rpg-
∂15-Nov-86 1213 kempf%hplabsc@hplabs.HP.COM Re: Meeting at X3J13
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 15 Nov 86 12:13:40 PST
Received: from hplabsc by hplabs.HP.COM ; Sat, 15 Nov 86 12:12:25 pst
Received: by hplabsc ; Sat, 15 Nov 86 12:11:57 pst
Date: Sat, 15 Nov 86 12:11:57 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8611152011.AA21017@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Meeting at X3J13
I will be on vacation for Dec. and therefore will be unable to
attend. However, I'll find out who from HP is going to attend
and make sure they have the latest draft of the standard from
SAIL.
Incidently, I hope the problems encountered during the development
of PCL are presented to the X3J13 committee and that the committee
takes them seriously, even to the point of changing the current
informal standard to resolve ambiguities. The Lisp community has
nothing to lose and everything to gain by strengthening CL
as a portable language. It will certainly help the objects standard
effort.
Jim Kempf kempf@hplabs
∂15-Nov-86 1353 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: discussion wanted
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 15 Nov 86 13:53:17 PST
Received: from ti-csl by csnet-relay.csnet id af11375; 15 Nov 86 2:32 EST
Received: from Jenner (jenner.ARPA) by tilde id AA00515; Thu, 13 Nov 86 17:00:54 cst
To: hpfclp!robert@HPLABS.HP.COM
Cc: common-lisp-object-system@SU-AI.ARPA
Subject: Re: discussion wanted
Date: 13-Nov-86 16:57:07
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2741295423@Jenner>
This standard is immense. I am worried that even though the proposal is
going to be well thought out, its usability is threatened by its size.
As pointed out by practically the entire OOPSLA panel on learnability,
one of the major contributors to the learnability of an object oriented
language is simplicity. Give them too many options and they balk or get
mired in details. I am worried about our users. I have to ask is all
this really necessary for the standard or is it just a good thing to
have on a rainy day?
There are several aspects related to the "size" of a standard.
First of all, a standard can be extensive without being complicated. You don' t
have to learn about the whole thing before being able to use it. Common Lisp
is a good example of such a standard. Only the first chapters of the book are
essential. If someone does not care about hash tables, he can skip the chapter and
go on.
Another aspect is that size and usefulness are related. If a standard is too small,
it might fall short for lots of applications, and there would be a lot of non portable,
incompatible extensions. An example of this is the call-out mechanism for the stock
hardware implementations of Common Lisp.
A third aspect of the size is: if a standard is large, its design phase is going to
be long because there are more chances to be inconsistent or incorrect.
I think that these aspects, even if not formally discussed in the mail, were in our
minds when we started. One of the tradeoffs we consider often is: do we want to
add this feature at the user interface level or leave it buried in the underlying
metaclass protocol. If we add the option at the user interface level, the standard
is growing but the user can take advantage of it without bothering with
meta objects, which are pretty esoteric for the programmer on the street.
I would consider the standard being extensive but I don't
consider it complicated. One can start working with objects by using only
DEFCLASS and DEFMETHOD, the default values options produce
reasonable results. Then one can refine his application when he is more
familiar with the standard.
The first two aspects should be considered most important when deciding tradeoffs.
The third should be considered a result of the first two. We will have to review
the drafts carefully.
Patrick.
∂16-Nov-86 1020 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Meeting at X3J13
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 16 Nov 86 10:20:38 PST
Received: from ti-csl by csnet-relay.csnet id aa01862; 16 Nov 86 13:09 EST
Received: from Jenner (jenner.ARPA) by tilde id AA15065; Sun, 16 Nov 86 11:54:12 cst
To: Dick Gabriel <RPG@SU-AI.ARPA>
Cc: common-lisp-object-system@SU-AI.ARPA
Subject: Re: Meeting at X3J13
Date: 16-Nov-86 10:22:41
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2741530958@Jenner>
It's possible for me, but I think that the function cell discussion
will be at the center this meeting.
-rpg-
Dick,
I you think we will be too short on time, we could meet the day before (Tuesday)
at TI in Dallas, I can get a small conference room reserved and the assurance that
nobody will disturb us.
Patrick.
∂17-Nov-86 1100 Bobrow.pa@Xerox.COM Re: Meeting at X3J13
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Nov 86 11:00:02 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 17 NOV 86 09:28:14 PST
Date: 17 Nov 86 09:27 PST
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Meeting at X3J13
In-reply-to: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET's message of 16 Nov
86 10:22:41
To: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
cc: RPG@SU-AI.ARPA, common-lisp-object-system@SU-AI.ARPA
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861117-092814-3939@Xerox>
It's possible for me, but I think that the function cell
discussion will be at the center this meeting.
-rpg-
Dick,
I you think we will be too short on time, we could meet the day
before (Tuesday) at TI in Dallas, I can get a small conference room
reserved and the assurance that nobody will disturb us.
Patrick.
I can't get there the day before. I was hoing that we could have this
despite other business (not with the whole committee).
-- danny
∂17-Nov-86 1807 Bobrow.pa@Xerox.COM Options of defclass
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Nov 86 18:07:20 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 17 NOV 86 14:34:22 PST
Date: 17 Nov 86 14:33 PST
Sender: Bobrow.pa@Xerox.COM
Subject: Options of defclass
To: Common-Lisp-Object-System@Sail.stanford.edu
cc: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861117-143422-434@Xerox>
BAD NAME
:default-value is a bad name for this feature. It leads a user to
believe that the value found in the class is used for initialization (or
worse, is found on access as in Loops). I propose we rename this option
to be
:initform initial-value-form
OMISSION
:type type-expression
should be allowed as it is in DEFSTRUCT. No requirements on its use
should be in the standard.
EXTENSION
:properties <any>
This allows users to attach their own properties to slots in a class.
It is uninterpreted by by the system. This allows user extensions to
information about slots to be done in a portable way. We found such
properties on slots to be most useful in Loops.
class-properties <class> <slot-name>
is a setf-able method that allows access to these properties.
An alternative name would be :user-data.
-- danny
∂17-Nov-86 1807 Gregor.pa@Xerox.COM change class protocol
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Nov 86 18:07:49 PST
Received: from Semillon.ms by ArpaGateway.ms ; 17 NOV 86 15:43:19 PST
Date: Mon, 17 Nov 86 15:39 PST
From: Gregor.pa@Xerox.COM
Subject: change class protocol
To: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <861117153938.3.GREGOR@AVALON.isl.parc.xerox.com>
Line-fold: no
This message outlines the change-class protocol currently in PCL, and
some issues which need to be worked out.
Here is an example of using the change-class protocol currently in PCL:
(defclass position () ())
(defclass x-y-position (position)
((x 0)
(y 0))
(:accessor-prefix position-))
(defclass rho-theta-position (position)
((rho 0)
(theta 0))
(:accessor-prefix position-))
(defmethod change-class-internal ((old x-y-position)
(new rho-theta-position))
;; Copy the position information from old to new to make new
;; be a rho-theta-position at the same position as old.
(let ((x (position-x old))
(y (position-y old)))
(setf (position-rho new) (atan y x)
(position-theta new) (sqrt (+ (* x x) (* y y))))))
(defmethod change-class-internal ((old rho-theta-position)
(new x-y-position))
...)
Now, the user can take an instance of the class x-y-position, like:
(setq p1 (make-instance 'x-y-position :x 2 :y 0))
and change it to an instance of the class rho-theta-position by saying:
(change-class p1 'rho-theta-position)
Note that the p1 instance itself will have its class changed.
To see how this works, here is the code for change-class:
(defun change-class (object new-class)
(let* ((old-class (class-of object))
(new-object (make new-class)))
;; Call change-class-internal so that a user-defined method
;; (or the default method) can copy the information from the
;; old instance to the dummy instance of the new class.
(change-class-internal object new-object)
;; Now that the dummy new-object has the right information,
;; move all that stuff into the old-instance.
(setf (iwmc-class-class-wrapper object)
(wrapper-of new-class))
(setf (iwmc-class-static-slots object)
(iwmc-class-static-slots new-object))
(setf (iwmc-class-dynamic-slots object)
(iwmc-class-dynamic-slots new-object))
object))
;;;
;;; The default implementation of change-class-internal just copies
;;; over all the slots, making new dynamic slots for slots that don't
;;; exist in the new class.
;;;
(defmeth change-class-internal ((old object) (new object))
(let ((all-slots (all-slots old)))
(iterate ((name in all-slots by cddr)
(value in (cdr all-slots) by cddr))
(put-slot-always new name value))))
Here are some issues which need to be resolved:
1. Is change-class a function or a generic-function?
Currently, it is a function. This means that the change-class protocol
is "hardwired". Should we make it a generic function so that the
protocol could be different for different meta-classes? If we want that
functionality, we may want to do something like (with different names of
course).
(defun change-class (object new-class)
(change-class-using-class (class-of object) new-class object))
(defmethod change-class-using-class ((old-class class)
(new-class class)
object)
.. this does what the current change class does ..
.. including call something like the current ..
.. change-class-internal ..
)
A related issue is that we have to spec out how the programming
environment calls change-class.
2. Is this internal protocol appropriate? I believe that it is
conceptually clear, but there is no doubt that it is not the most
efficient for all hardwares. Is it possible to come up with a protocol
which is simple and allows the most efficient implementation across
hardwares? Is it even possible to come up with a protocol which allows
the most efficient implementation across hardwares?
-------
∂17-Nov-86 1809 Gregor.pa@Xerox.COM portable interface to code walker
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Nov 86 18:08:05 PST
Received: from Semillon.ms by ArpaGateway.ms ; 17 NOV 86 16:10:52 PST
Date: Mon, 17 Nov 86 16:10 PST
From: Gregor.pa@Xerox.COM
Subject: portable interface to code walker
To: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <861117161022.4.GREGOR@AVALON.isl.parc.xerox.com>
Line-fold: no
During the last discussion of with-slots, we agreed that we would
specify a portable, "programmatic" interface to the code walker which
people could use to write portable variants of with. This message
contains a first stab at that.
WALK-VARIABLES form environment function
walks over form, doing macroexpansions etc.
Each time the walk encounters a symbol which is going to be evaluated,
it calls function with two arguments. The first argument is the symbol.
The second argument is T if that symbol has been bound during the walk
to this place, nil otherwise. Whatever function returns is used in
place of the symbol.
Each time the walk encounters a symbol which is going to be set, it
calls function with two arguments. The first argument is a form like
(SETQ <symbol> <form>) the second argument is as described above.
Whatever function returns is used in place of the setq form.
This protocol seems to be sufficient for writing new kinds of
with-slots. But somehow, it is tempting to define some sort of more
general walker so that people can use it for other things too. Maybe it
would be enough to fix Common Lisp so that it is in fact possible to
write a truly portable code walker and then let people use that?
-------
∂18-Nov-86 0738 kempf%hplabsc@hplabs.HP.COM Re: change class protocol
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 18 Nov 86 07:38:02 PST
Received: from hplabsc by hplabs.HP.COM ; Tue, 18 Nov 86 07:36:11 pst
Received: by hplabsc ; Tue, 18 Nov 86 07:35:38 pst
Date: Tue, 18 Nov 86 07:35:38 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8611181535.AA17978@hplabsc>
To: Common-Lisp-Object-System@Sail.stanford.edu, Gregor.pa@Xerox.COM
Subject: Re: change class protocol
I think that change-class would be most appropriate as a generic
function, to allow different metaclasses the option of implementing
their own protocol.
Jim Kempf kempf@hplabs
∂18-Nov-86 0804 kempf%hplabsc@hplabs.HP.COM Re: portable interface to code walker
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 18 Nov 86 07:57:20 PST
Received: from hplabsc by hplabs.HP.COM ; Tue, 18 Nov 86 07:55:58 pst
Received: by hplabsc ; Tue, 18 Nov 86 07:55:25 pst
Date: Tue, 18 Nov 86 07:55:25 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8611181555.AA18071@hplabsc>
To: Common-Lisp-Object-System@Sail.stanford.edu, Gregor.pa@Xerox.COM
Subject: Re: portable interface to code walker
>WALK-VARIABLES form environment function
>
>walks over form, doing macroexpansions etc.
>
>Each time the walk encounters a symbol which is going to be evaluated,
>it calls function with two arguments. The first argument is the symbol.
>The second argument is T if that symbol has been bound during the walk
>to this place, nil otherwise. Whatever function returns is used in
>place of the symbol.
I'm not quite sure what you mean by "evaluated". Do you mean
"evaluated in the context of the code walk?" Or "evaluated by
Common Lisp EVAL?" And what is "this place"? The symbol? Assuming
"yes" and that you mean "evaluated in the context of the code walk",
then this looks much like the LET-PSEUDO with which we've extended
Common Lisp (hidden from the user) to do something similar. The
difference is that LET-PSEUDO is a sort of "symbol-macro" facility
which always does the substitution of a form for a symbol at
macroexpansion time, while WALK-VARIABLES would give the programmer
control over when to do the substitution.
>Each time the walk encounters a symbol which is going to be set, it
>calls function with two arguments. The first argument is a form like
>(SETQ <symbol> <form>) the second argument is as described above.
>Whatever function returns is used in place of the setq form.
>
>This protocol seems to be sufficient for writing new kinds of
>with-slots. But somehow, it is tempting to define some sort of more
>general walker so that people can use it for other things too. Maybe it
>would be enough to fix Common Lisp so that it is in fact possible to
>write a truly portable code walker and then let people use that?
This latter point is the most important, I think. If the X3J committe
is receptive and the proposal is specific enough, hooks into Common Lisp
to allow people to do portable code walkers would certainly be more
desirable. In fact, the kind of thing WITH needs to have done is,
at some level, part of every compiler implementation. The portable hooks
would expose this functionality to embedded language developers,
in the same manner as macros do for developing s-expression oriented syntax.
Jim Kempf kempf@hplabs
∂18-Nov-86 1026 Gregor.pa@Xerox.COM Re: change class protocol
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Nov 86 10:26:25 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 18 NOV 86 10:11:55 PST
Date: 18 Nov 86 10:11 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: change class protocol
In-reply-to: Ken kahn <kahn.pa>'s message of 18 Nov 86 09:38 PST
To: kahn.pa@Xerox.COM
cc: kempf%hplabsc@hplabs.HP.COM,
Common-Lisp-Object-System@Sail.stanford.edu, Gregor.pa@Xerox.COM
Message-ID: <861118-101155-1879@Xerox>
Yes, there is a bug in the code, it won't accept the name of a class.
But it is supposed to. So the second argument to change-class can be
either a class or the name of a class.
∂18-Nov-86 1026 kahn.pa@Xerox.COM Re: change class protocol
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Nov 86 10:26:20 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 18 NOV 86 09:38:31 PST
Date: 18 Nov 86 09:38 PST
Sender: kahn.pa@Xerox.COM
Subject: Re: change class protocol
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Tue,
18 Nov 86 07:35:38 pst
To: kempf%hplabsc@hplabs.HP.COM
cc: Common-Lisp-Object-System@Sail.stanford.edu, Gregor.pa@Xerox.COM
From: Ken kahn <kahn.pa@Xerox.COM>
Message-ID: <861118-093831-1834@Xerox>
I agree with Jim that there should be a change-class-using-class.
Also the example
(change-class p1 'rho-theta-position)
uses the name of a class instead of the class. The code does things
like
(wrapper-of new-class). MAKE-INSTANCE accepts either a class or the
name of a class, why shouldn't that be the general rule.
----- ken
∂18-Nov-86 1710 kahn.pa@Xerox.COM Re: Second installment of comments on Functions chapter
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Nov 86 17:09:52 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 18 NOV 86 16:55:12 PST
Date: 18 Nov 86 16:55 PST
Sender: kahn.pa@Xerox.COM
Subject: Re: Second installment of comments on Functions chapter
In-reply-to: Gregor Kiczales <Gregor.pa>'s message of 14 Nov 86 17:21
PST
To: Gregor.pa@Xerox.COM
cc: MOON%ML.AI.MIT.EDU@MC.LCS.MIT.EDU,
Common-Lisp-Object-System@SU-AI.ARPA
From: Ken kahn <kahn.pa@Xerox.COM>
Message-ID: <861118-165512-2491@Xerox>
I like the method-lambda macro. It should be noted that along with
generic-function-lambda that they can only sometimes be used where a
LAMBDA can be.
E.g. (funcall #'(method-lambda ...) ...) works while ((method-lambda
...) ...) doesn't. Given that its unclear whether it would be better if
such macros expanded to (FUNCTION (LAMBDA ...)) so that one would write
(funcall (method-lambda ...) ...) instead. For symmetry one could write
a LAMBDA macro that expanded into (FUNCTION (LAMBDA ...)).
Maybe I'm being dense but I don't see how
Given method-lambda and generic-function-lambda We see no need
to include any of the variants of labels or flet we have been
talking about. It is easy to implement any of them using
method-lambda and generic-function-lambda.
Would a GFLET, for example, expand to a FLET that used the CDR of the
expansion of a generic-function-lambda?
----- ken
∂21-Nov-86 2027 Moon@STONY-BROOK.SCRC.Symbolics.COM Options of defclass
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 21 Nov 86 20:27:43 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 7307; Fri 21-Nov-86 23:08:23 EST
Date: Fri, 21 Nov 86 23:08 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Options of defclass
To: Common-Lisp-Object-System@Sail.stanford.edu
In-Reply-To: <861117-143422-434@Xerox>
Message-ID: <861121230816.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 17 Nov 86 14:33 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
BAD NAME
:default-value is a bad name for this feature. It leads a user to
believe that the value found in the class is used for initialization (or
worse, is found on access as in Loops).
Is the issue here to make it clear to the user that the argument to
:default-value is a form to be evaluated, not a constant object to be
stored directly into the slot? In other words, is the problem with
the word "value" or with the word "default" or both?
I propose we rename this option to be
:initform initial-value-form
I'm not too happy with this name, since it is not English. Its only
virtue is that it is used in a few places (lambda-lists) in CLtL (but
not in the Common Lisp language itself, only in the description of the
language), so it isn't an entirely new piece of jargon. On the other
hand, in another part of CLtL (defstruct) these are called default-inits
instead of init-forms, and in yet another part (defvar) they are called
initial-values.
I'm not too happy with the name :default-value either. Anyone have
a better idea?
Remind me why we didn't like using = as the name of this slot-option.
OMISSION
:type type-expression
should be allowed as it is in DEFSTRUCT. No requirements on its use
should be in the standard.
I don't see what use this could be, but I don't see how it could hurt,
other than by making the language larger. Let's go ahead and put it in.
EXTENSION
:properties <any>
This allows users to attach their own properties to slots in a class.
It is uninterpreted by by the system. This allows user extensions to
information about slots to be done in a portable way. We found such
properties on slots to be most useful in Loops.
class-properties <class> <slot-name>
is a setf-able method that allows access to these properties.
An alternative name would be :user-data.
If I had suggested :properties you would have told me to do it with
meta-objects instead of cluttering up the syntax. I don't think this
belongs here.
If we want to allow users to extend the syntax of defclass, rather than
making their own macro, we certainly should make the user-defined
extensions have a syntax consistent with the built-in features, rather
than requiring a prefix :properties on user-defined slot-options. It's
always a mistake to draw lines between "the user" and "the system"; in
Lisp, things are built up in layers and one man's user is another man's
system.
∂21-Nov-86 2122 Moon@STONY-BROOK.SCRC.Symbolics.COM Class precedence list, underconstrained method ordering
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 21 Nov 86 21:22:22 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 7334; Sat 22-Nov-86 00:20:39 EST
Date: Sat, 22 Nov 86 00:20 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Class precedence list, underconstrained method ordering
To: Common-Lisp-Object-System@SU-AI.ARPA
cc: KMP@STONY-BROOK.SCRC.Symbolics.COM
In-Reply-To: <860925145850.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <861122002029.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
I have been investigating the proposed extension described in mail included
below, using some tools I wrote for the purpose. It turns out that the
proposed extension would signal an error for many quite legitimate looking
programs. So far I have not thought of any weakened form of the proposed
extension that I would wish to propose for inclusion in the standard.
I found a few cases where the order of the methods really doesn't matter,
and I found a few cases that are really bugs in the programs I was
analyzing, but the preponderance of the cases I found are like this:
(defclass stuff (class-1 class-2) ())
(defclass class-1 (class-1-internal) ())
(defclass class-2 (class-2-internal) ())
(defmethod funk ((x class-1-internal) ...) ...)
(defmethod funk ((x class-2-internal) ...) ...)
where the programmer definitely expected the first method to shadow
the second method. The problem here is that the local ordering rules
(rules 1 and 2 on p.1-14 of our draft document) do not specify any
constraint on the ordering of class-1-internal and class-2-internal.
Nevertheless, the programmer was clearly thinking that class-1-internal
is part of class-1, and class-2-internal is part of class-2, and
since class-1 goes before class-2 then class-1-internal must go before
class-2-internal. This is faulty as logic but good as intuition.
The problem is this: programmers use component classes in two different
ways, and the language does not provide any way to record the programmer's
intent. (1) The components of a class are its own business and the internal
structure of that class should not be affected by mixing it with other
classes. (2) A class is a selection from a pool of available, publicly
known mixins, and the particular set selected is part of the interface of
that class. I don't know whether it is worth adding to the language a way
for programmers to distinguish between these two uses of superclasses. The
advantage would be that the class system would be able to tell a programmer
that he was breaking a class designed according to (1) by treating it
according to (2), i.e. mixing it with another class built from some of the
same superclasses. I'll think about this more.
The reason these programs work, in spite of their apparently
underconstrained ordering, is that Flavors doesn't just follow local
ordering rules 1 and 2. It also has a rule, whose importance I didn't fully
grasp until now, that when class-1 and class-2 are mixed together, all of
the components of class-1 must precede all of the components of class-2,
provided there are no intersections. This is what rule 3 and the
tree-walking discussion on p.1-14 are both about. We should have this
somewhat nonlocal rule in the Common Lisp object standard but I think we
need a more easily understood formulation of the rule than has yet been
offered. What's in the draft document on p.1-14 is quite precise, but its
implication that class-1's components are guaranteed to precede class-2's
components is a little hard to grasp.
Also, the remark on p.1-15 about well-conceived programs needs to be
modified in light of the discovery (at least to me it's a discovery) that
relying only on the strictly local ordering rules isn't going to work in the
real world. The (pie apple fruit cinnamon spice) ordering is guaranteed by
rule 3, but if you did (defclass humble-pie (pie spice fruit) ()), its
components would be (humble-pie pie apple cinnamon spice fruit), so if the
ordering of spice and fruit matters to the correct functioning of pie, and
pie is going to be used as a building-block, you should make that constraint
explicit. Or if had a way for programmers to distinguish, the definers of
apple and cinnamon could declare that these were type (1) classes. Either
way the attempt to define humble-pie would signal an error, saying that
fruit must precede spice.
I suspect this issue may be what some of Danny's class precedence
suggestions were really about, although he didn't phrase them this way.
Date: Thu, 25 Sep 86 14:58 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Date: 25 Sep 86 07:59 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The search I would be interested in is not the one where there are
differences of order only, but ones in which a subclass has the classes
in a different order than a super. This could lead to strangeness for a
user who tests an operation on a superclass, and finds then happening
differently in a subclass.
That is exactly what the New Flavors ordering rules, as compared with either
breadth-first or depth-first search, are intended to avoid. It might be that
there are cases where they don't avoid this problem, but I'd have to see
a specific example. The proposed extension, which I kind of like but have
neither implemented nor evaluated its effect on real programs, deals more
stringently with this issue by examining all pairs of component classes whose
order is unconstrained and determining whether exchanging them would alter
any inherited methods; if not, their order doesn't matter, because it doesn't
affect behavior. If so, signal an error. This extension would ensure that
no matter which of the possible total orderings consistent with the partial
ordering is chosen, the behavior is the same.
Even though I like this idea (due to KMP originally I believe) I can't
support putting it into a standard, since it hasn't been tried in the
real world.
∂22-Nov-86 1048 RPG Options of Defclass
To: common-lisp-object-system@SAIL.STANFORD.EDU
``Remind me why we didn't like using = as the name of this slot-option.''
If you write
(defclass foo (baz) (ztesch :initable t = nil))
it looks funny. If you insist that the `=' appear immediately after the
slot name, you've possibly imposed unnecessary syntax and non-Lispiness on
the construct.
`` :type type-expression
should be allowed as it is in DEFSTRUCT. No requirements on its use
should be in the standard.
I don't see what use this could be, but I don't see how it could hurt,''
Sometimes a compiler will be able to optimize things a little given some
information like this. It might not be that the storage or its direct
handling will improve or change, but, perhaps, some other operation can be
slightly improved - such a being able to emit the machine addition
instruction with only overflow checking - when the slot, directly, is
involved in an arithmetic expression.
``If I had suggested :properties you would have told me to do it with
meta-objects instead of cluttering up the syntax. I don't think this
belongs here.''
I said this myself, but acceded.
-rpg-
∂24-Nov-86 1810 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Meeting at X3J13
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Nov 86 18:09:58 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 8973; Mon 24-Nov-86 21:07:42 EST
Date: Mon, 24 Nov 86 21:07 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Meeting at X3J13
To: common-lisp-object-system@SU-AI.ARPA
Message-ID: <861124210743.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
I'm not going to attend the Dallas X3J13 meeting. This is partly
because I'm trying to cut down on travel, and partly because I have an
excessively low tolerance for exercises in futility. I'll try to make
it to the next X3J13 meeting, especially if the object-oriented
programming standard is going to be discussed in a serious way at that
meeting.
As far as I know Sonya isn't going to Dallas either. Thus I don't think
it will be possible to use Dallas for a face to face meeting of the whole
object-oriented programming working group. I believe we can continue to
make progress over the network if we concentrate on the important issues.
∂25-Nov-86 1339 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: portable interface to code walker
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 25 Nov 86 13:38:44 PST
Received: from ti-csl by csnet-relay.csnet id at04601; 25 Nov 86 16:21 EST
Received: from Jenner (jenner.ARPA) by tilde id AA04661; Fri, 21 Nov 86 14:57:42 cst
To: Gregor.pa@XEROX.COM
Cc: Common-Lisp-Object-System@SU-AI.ARPA
Subject: Re: portable interface to code walker
Date: 21-Nov-86 15:01:10
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2741979667@Jenner>
Gregor,
There might be problems with a code walker that figures out substitutions
for symbols after macroexpanding forms.
Consider this example:
(with object
(pushnew item l) ;l is a slot of object.
....)
Well, (pushnew item l) will expand into
(if (member item l)
l
(setq l (cons item l)))
The fact that l is referred to twice is a problem.
It is so because PUSHNEW optimized the general expression
(let ((tmp l) (tmp1 item))
(if (member item tmp)
tmp
(setf l (cons tmp1 tmp))))
based on the fact that l and item are symbols.
Those assumptions would be wrong if the symbol is substituted after the macroexpansion.
Something like Jim Kempf was suggesting would be more appropriate.
Macroexpand would try to substitute symbols based on the macroexpand environment
set up by a special form like SYMBOL-LET.
(with object
(pushnew item l)
.....)
could expand into
(SYMBOL-LET ((l (l object)))
(pushnew item l)
....)
PUSHNEW would macroexpand L and ITEM and produce:
(let ((tmp (l object)))
(if (member item tmp)
tmp
(setf (l object) (cons item tmp))))
Patrick.
∂25-Nov-86 1445 Gregor.pa@Xerox.COM :accessor-prefix questions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 25 Nov 86 14:44:47 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 25 NOV 86 13:25:29 PST
Date: 25 Nov 86 13:23 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: :accessor-prefix questions
To: Common-Lisp-Object-System@Sail.Stanford.edu
cc: Gregor.pa@Xerox.COM
Message-ID: <861125-132529-2940@Xerox>
I have some questions about the :accessor-prefix option to defclass (all
of these questions also apply to :reader-prefix).
1. Is there a special way to tell :accessor-prefix to make the names of
the accessors just be the names of the slots? In other words, is there
a special flag which says, don't call symbol-name or intern at all.
Assuming the answer is yes, and the special flag is NIL, the following
behavior would result:
(defclass foo () (defclass foo ()
(tv:x (tv:x
tv:y tv:y
a a
b) b)
(:accessor-prefix "") (:accessor-prefix nil))
Would define methods on the Would define methods on the
generic functions: generic functions:
X, Y, A and B TV:X, TV:Y, A and B
1a. If there is such a special flag, what is it? NIL, "" something
else?
2. Whether there is or isn't such a special flag, what do we do in the
following case:
(defclass foo ()
(tv:x
si:x)
(:accessor-prefix foo-))
3. Do we really want to allow strings as an argument to
:accessor-prefix? Is it enough to just allow symbols?
4. Should we allow a second argument to :accessor-prefix which would be
the package to intern the generated names in.
Obviously, for each of these questions there will be cases where the
programmers could use the extra power provided. For each question, how
do we reconcile our answer with simplicity in understanding the behavior
of defclass?
My current set of answers is:
1. No special flag to say don't call intern. People can use :accessor
for this case.
1a. doesn't apply
2. defclass must signal an error when it defines two accessors with the
same name which access different slots.
3. Allowing strings is OK, but not necessary. People who want
lower-case characters in the print names of the symbols generated could
deal with having to type |foo-| quite easily I think.
4. A package argument to :accessor-prefix is not necessary given the
existence of :accessor, but it might be a good idea to have it anyways.
I remember discussions about having a package argument to :conc-name,
but I forget what the issues were.
∂26-Nov-86 0819 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: portable interface to code walker
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 26 Nov 86 08:16:22 PST
Received: from ti-csl by csnet-relay.csnet id aa13185; 26 Nov 86 10:39 EST
Received: from Jenner (jenner.ARPA) by tilde id AA01612; Wed, 26 Nov 86 07:59:18 cst
To: Gregor.pa@XEROX.COM
Cc: Common-Lisp-Object-System@SU-AI.ARPA
Subject: Re: portable interface to code walker
Date: 26-Nov-86 07:59:21
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2742386358@Jenner>
Gregor,
There might be problems with a code walker that figures out substitutions
for symbols after macroexpanding forms.
Consider this example:
(with object
(pushnew item l) ;l is a slot of object.
....)
Well, (pushnew item l) will expand into
(if (member item l)
l
(setq l (cons item l)))
The fact that l is referred to twice is a problem.
It is so because PUSHNEW optimized the general expression
(let ((tmp l) (tmp1 item))
(if (member item tmp)
tmp
(setf l (cons tmp1 tmp))))
based on the fact that l and item are symbols.
Those assumptions would be wrong if the symbol is substituted after the macroexpansion.
Something like Jim Kempf was suggesting would be more appropriate.
Macroexpand would try to substitute symbols based on the macroexpand environment
set up by a special form like SYMBOL-LET.
(with object
(pushnew item l)
.....)
could expand into
(SYMBOL-LET ((l (l object)))
(pushnew item l)
....)
PUSHNEW would macroexpand L and ITEM and produce:
(let ((tmp (l object)))
(if (member item tmp)
tmp
(setf (l object) (cons item tmp))))
Patrick.
∂26-Nov-86 0857 Bobrow.pa@Xerox.COM Re: :accessor-prefix questions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Nov 86 08:57:36 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 26 NOV 86 08:50:01 PST
Date: 26 Nov 86 08:50 PST
Sender: Bobrow.pa@Xerox.COM
Subject: Re: :accessor-prefix questions
In-reply-to: Gregor Kiczales <Gregor.pa>'s message of 25 Nov 86 13:23
PST
To: Gregor.pa@Xerox.COM
cc: Common-Lisp-Object-System@Sail.Stanford.edu
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861126-085001-3808@Xerox>
My current set of answers is:
1. No special flag to say don't call intern. People can use
:accessor for this case. 1a. doesn't apply
I agree.
2. defclass must signal an error when it defines two accessors
with the same name which access different slots.
I agree
3. Allowing strings is OK, but not necessary. People who want
lower-case characters in the print names of the symbols generated
could deal with having to type |foo-| quite easily I think.
I don't agree. If there is no special flag, then allowing strings or
symbols is no cost. The symbol NIL doesn't mean no prefix. Only the
string "" does.
4. A package argument to :accessor-prefix is not necessary
given the existence of :accessor, but it might be a good idea to
have it anyways. I remember discussions about having a package
argument to :conc-name, but I forget what the issues were.
I don't agree. In this unusual case, either use the :accessor option,
or do explicit defmethods in the desired package.
-- danny
∂26-Nov-86 0910 Bobrow.pa@Xerox.COM "Do it using the meta-object protocol"
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Nov 86 09:09:22 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 26 NOV 86 09:08:28 PST
Date: 26 Nov 86 09:05 PST
Sender: Bobrow.pa@Xerox.COM
Subject: "Do it using the meta-object protocol"
To: Common-Lisp-Object-System@Sail.Stanford.edu
cc: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861126-090828-3847@Xerox>
Moon says:
If I had suggested :properties you would have told me to do it
with meta-objects instead of cluttering up the syntax. I don't
think this belongs here.
Since I believe this argument and was about to make it for two more
"feature" that have been in the writeup for a while, I guess I give in.
The two features I use that argument for are from method combination:
:method-arguments
:interface
I know they have been useful in complex combination forms in Flavors,
but can be implemented, if really necessary, in the methods that compute
the code for the method combination by a specialized class.
-- danny
∂26-Nov-86 0913 Bobrow.pa@Xerox.COM Re: Options of defclass
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Nov 86 09:13:16 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 26 NOV 86 09:13:12 PST
Date: 26 Nov 86 09:13 PST
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Options of defclass
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 21 Nov 86 23:08 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@Sail.stanford.edu
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861126-091312-3868@Xerox>
Moon says:
I'm not too happy with this name [:initform], since it is not
English...I'm not too happy with the name :default-value either.
Would you prefer the longer :initialize-with, :initialization-form or
perhaps :default-value-form. Maybe :default-form would work. My problem
with :default-value is that Loops had them -- and they were values not
forms to evaluate.
-- danny
∂28-Nov-86 1609 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: portable interface to code walker
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Nov 86 16:09:09 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 11089; Fri 28-Nov-86 18:54:42 EST
Date: Fri, 28 Nov 86 18:54 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: portable interface to code walker
To: Common-Lisp-Object-System@Sail.stanford.edu
In-Reply-To: <DUSSUD.2742386358@Jenner>,
<8611181555.AA18071@hplabsc>,
<861117161022.4.GREGOR@AVALON.isl.parc.xerox.com>
Message-ID: <861128185424.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
I prefer Jim Kempf's suggestion that the documented interface be in
terms of a macro over Gregor Kiczales' suggestion that the documented
interface be in terms of a code-walking function. The implementation of
the macro can use a code walker or any other technique appropriate to
the particular implementatation. Documenting just the macro is more
abstract and leaves more freedom to the implementation, without any
decrease in power as far as I can see. It also makes the documentation
a lot simpler, since as Gregor noted there is the temptation to include
an elaborate code-walking facility.
I've thought about Patrick Dussud's argument that the substitution for
symbols should not be done simply by expanding all macros and then
substituting, and I believe it. If it were safe to assume that reading
a slot cannot have side effects, then the issue would be only one of
efficiency, not correctness. I don't think that assumption is safe,
however, since reading a slot can invoke a method, and the method might
implement so-called "active values." Thus I believe it is necessary for
the expansion of macros inside with-slots to be aware that the lexical
environment defines the meanings of the slot names, i.e. for the
macroexpansion and substitution to be done in one pass instead of two.
The names let-pseudo and symbol-let don't appeal to me; somehow they
don't seem to convey the semantics clearly. Symbolics Common Lisp has
something similar, called "symbol-macros", so the name "symbol-macrolet"
is my suggestion. This conveys the idea that it is similar to macrolet
but substitutes for symbols rather than for macro invoking lists.
∂28-Nov-86 1619 Moon@STONY-BROOK.SCRC.Symbolics.COM :accessor-prefix questions
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Nov 86 16:18:59 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 11096; Fri 28-Nov-86 19:17:15 EST
Date: Fri, 28 Nov 86 19:16 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: :accessor-prefix questions
To: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <[ML.AI.MIT.EDU].1835.861113.MOON>,
<861125-132529-2940@Xerox>,
<861126-085001-3808@Xerox>
Message-ID: <861128191658.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 13 Nov 86 01:40:21 EST
From: "David A. Moon" <MOON%ML.AI.MIT.EDU@MC.LCS.MIT.EDU>
With :accessor-prefix and :reader-prefix, how does one specify that the
accessor name is to be the same as the slot name? A prefix of "" won't
work, since that re-interns the accessor name in the current package. Do
we need two more options for this? Should we treat the symbol NIL as a
special case? I think two more options would be more tasteful.
I still think additional options would be more tasteful than treating
NIL, or anything else, as a special case.
Executive summary: I think issues 2, 3, and 4 are clear; issue 1 requires
more discussion before making a decision.
Date: 25 Nov 86 13:23 PST
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
I have some questions about the :accessor-prefix option to defclass (all
of these questions also apply to :reader-prefix).
1. Is there a special way to tell :accessor-prefix to make the names of
the accessors just be the names of the slots? In other words, is there
a special flag which says, don't call symbol-name or intern at all.
Assuming the answer is yes, and the special flag is NIL, the following
behavior would result:
(defclass foo () (defclass foo ()
(tv:x (tv:x
tv:y tv:y
a a
b) b)
(:accessor-prefix "") (:accessor-prefix nil))
Would define methods on the Would define methods on the
generic functions: generic functions:
X, Y, A and B TV:X, TV:Y, A and B
1a. If there is such a special flag, what is it? NIL, "" something
else?
My current set of answers is:
1. No special flag to say don't call intern. People can use :accessor
for this case.
1a. doesn't apply
Date: 26 Nov 86 08:50 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
I agree.
I am surprised, since I thought you were an advocate of the accessors
having the same names as the slots. If you aren't, we should hear from
someone who advocates that position before making it difficult to do. I
assume that an advocate of that position would not want to have to write
(foo :accessor foo) for every slot and would not be happy with the
accessor having almost the same name as the slot, but in a different
package.
By the way, advocates of that position are necessarily opposed to
combining the function cell and value cell, right?
[Gregor again]
2. Whether there is or isn't such a special flag, what do we do in the
following case:
(defclass foo ()
(tv:x
si:x)
(:accessor-prefix foo-))
2. defclass must signal an error when it defines two accessors with the
same name which access different slots.
[Danny again]
I agree
So do I.
[Gregor again]
3. Do we really want to allow strings as an argument to
:accessor-prefix? Is it enough to just allow symbols?
3. Allowing strings is OK, but not necessary. People who want
lower-case characters in the print names of the symbols generated could
deal with having to type |foo-| quite easily I think.
[Danny again]
I don't agree. If there is no special flag, then allowing strings or
symbols is no cost. The symbol NIL doesn't mean no prefix. Only the
string "" does.
I shamefacedly admit that I never realized that allowing strings would
introduce a problem with alphabetic case. Consider the plight of people
who write their source code in lower case; they would have to upper-case
the string. Danny notwithstanding, I think this makes it clear that strings
should not be allowed here. Even the null string should have to be written
|| rather than "".
[Gregor again]
4. Should we allow a second argument to :accessor-prefix which would be
the package to intern the generated names in.
4. A package argument to :accessor-prefix is not necessary given the
existence of :accessor, but it might be a good idea to have it anyways.
I remember discussions about having a package argument to :conc-name,
but I forget what the issues were.
[Danny again]
I don't agree. In this unusual case, either use the :accessor option,
or do explicit defmethods in the desired package.
I agree with Danny, the package argument is unnecessary complexity.
∂30-Nov-86 1238 Masinter.pa@Xerox.COM Re: :accessor-prefix questions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Nov 86 12:38:22 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 NOV 86 12:38:21 PST
Date: 30 Nov 86 12:38 PST
From: Masinter.pa@Xerox.COM
Subject: Re: :accessor-prefix questions
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 28 Nov 86 19:16 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861130-123821-5477@Xerox>
"... I am surprised, since I thought you were an advocate of the
accessors
having the same names as the slots. If you aren't, we should hear from
someone who advocates that position before making it difficult to do. "
I want to advocate a requirement, but the requirement isn't exactly as
stated. The requirement is that the packages of the accessors depend
only upon information explicitly available within the defining form once
the defining form has been read. With current DEFSTRUCT, the package of
generated accessors depends on the value of *package* at the time the
DEFSTRUCT is evaluated, rather than at the time the DEFSTRUCT is read.
However, for every other definitional form in Common Lisp, the only
dependence on *package* (and other read-environment variables such as
*read-base*) is only on the value at read time.
This requirement can be satisfied either by making the accessor names
the same as the slot names, or by making the accessor names be interned
into the *same* package as the slots.
This is required, for example, in residential environments where the
time of evaluation of a definitional form might be different than the
time that form was READ. It is good programming language design to keep
to a minimum the amount that the semantics of a given form depends upon
the dynamic environment and to separate out syntactic features from
semantic ones; *package* describes a syntactic feature rather than a
semantic one.
∂30-Nov-86 1402 Gregor.pa@Xerox.COM Re: :accessor-prefix questions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Nov 86 14:02:02 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 NOV 86 14:02:02 PST
Date: 30 Nov 86 14:01 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: :accessor-prefix questions
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 28 Nov 86 19:16 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861130-140202-5512@Xerox>
This message answers David Moon's comments about :accessor-prefix and
has some changes to my original position on these questions.
The major point of this message is that we could use "" as a special
flag to :accessor-prefix to mean don't re-intern the symbols, just use
the symbol which names the slot as the accessor.
Question # 1 was:
Should there be a special flag to say don't call intern. Previously, I
had said that I thought we did not need such a flag. But as you point
out,
Date: Fri, 28 Nov 86 19:16 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
(this was actually to Danny, but Danny and I were advocating
the same position)
I am surprised, since I thought you were an advocate of the
accessors having the same names as the slots. If you aren't, we
should hear from someone who advocates that position before making
it difficult to do.
I had missed the point that not having such a flag would make it
difficult to have accessors have the same names as slots. I now realize
that a flag like this is necessary.
Question # 3 was:
Do we want to allow strings as an argument to :accessor-prefix? Is it
enough to just allow symbols?
I shamefacedly admit that I never realized that allowing
strings would introduce a problem with alphabetic case. Consider
the plight of people who write their source code in lower case;
they would have to upper-case the string. Danny notwithstanding, I
think this makes it clear that strings should not be allowed here.
Even the null string should have to be written || rather than "".
Good, that means that we can outlaw strings here. Given that we do need
some mechanism for specifying that the accessors should just be symbols
which name the slots, I propose that we use "" as a special argument to
:accessor-prefix and :reader-prefix to have this meaning. I agree that
this is a little hackish, but I would rather do that than introduce two
whole new options for this purpose.
Question #4 was:
Should we allow a second argument to :accessor-prefix which would be the
package to intern the generated names in.
Previously, I said this might be a good idea. Danny said it would not,
and Moon agreed with Danny by saying:
I agree with Danny, the package argument is unnecessary
complexity.
Since then I remembered previous discussions about adding such a package
argument to :conc-name and remembered the problems why it would be a bad
idea. Specifically, having an explicit package argument would make
changing the in-package statement for a file not affect the accessors
created by defclass. It would mean that moving a program to another
package would require a lot more than just editing a few in-package
statements. So I now think that an explicit package argument is an
extremely bad idea.
∂30-Nov-86 1737 Gregor.pa@Xerox.COM Re: portable interface to code walker
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Nov 86 17:37:42 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 NOV 86 17:35:51 PST
Date: 30 Nov 86 17:35 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: portable interface to code walker
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 28 Nov 86 18:54 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <861130-173551-1018@Xerox>
I have been thinking about Patrick's message for some time. I don't
believe the argument he is presenting about symbol-macros.
Date: 21 Nov 86 15:01:10
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
(note: I have edited the example Patrick gave slightly, to
correct simple problems like not using gensyms where
appropriate and not using the correct syntax for with-slots)
There might be problems with a code walker that figures out
substitutions for symbols after macroexpanding forms.
Consider this example:
(with-slots (object)
(pushnew item l) ;l is a slot of object.
....)
Well, (pushnew item l) will expand into
(if (member item l)
l
(setq l (cons item l)))
The fact that l is referred to twice is a problem.
It is because PUSHNEW optimized the general expression
(let ((#:g0001 l)
(#:g0002 item))
(if (member #:g0002 #:g0001)
#:g0001
(setf l (cons #:g0002 #:g0001))))
based on the fact that l and item are symbols.
Those assumptions would be wrong if the symbol is substituted
after the macroexpansion.
Date: Fri, 28 Nov 86 18:54 EST
From: David A. Moon
I've thought about Patrick Dussud's argument that the
substitution for symbols should not be done simply by expanding all
macros and then substituting, and I believe it. If it were safe to
assume that reading a slot cannot have side effects, then the issue
would be only one of efficiency, not correctness. I don't think
that assumption is safe, however, since reading a slot can invoke a
method, and the method might implement so-called "active values."
Thus I believe it is necessary for the expansion of macros inside
with-slots to be aware that the lexical environment defines the
meanings of the slot names, i.e. for the macroexpansion and
substitution to be done in one pass instead of two.
When you say "If it were safe to assume that reading a slot cannot have
side effects, then the issue would be only one of efficiency, not
correctness", you touch on the source of my disagreement with the
argument you and Patrick are presenting.
Basically, I think that it is bad design for the implementor of a macro
to blurr efficiency and correctness this way. In particular, I believe
it is bad design for a macro to expand differently based on whether or
not evaluating some of its argumenst can have side effects. I believe
that:
(pushnew <item> <list>)
Should expand to:
(let ((#:g0001 <list>)
(#:g0002 <item>))
(if (member #:g0002 #:g0001)
#:g0001
(setf <list> (cons #:g0002 #:g0001))))
or, maybe (setf <list> (adjoin <item> <list>))
regardless of the value of <item> and <list>. It is the job of the
compiler, not the pushnew macro, to perform transformations on this code
which preserve semantics but improve efficiency.
This may sound like naive folly, but look at the consequences of
implementing macros the way you and Patrick suggest using the very
change that you and Patrick are proposing we make to the language.
Any macro which does optimizations like the one Patrick presents is
going to have to be changed in order to add with-slots to the language.
Either these macros will have to be changed to respect symbol macros as
you and Patrick suggest, or they will have to be changed to expand the
way I suggest so that a simple code walker can be used to implement
with-slots.
The fact that adding with-slots to the language breaks macros which do
the kind of side-effect analysis in Patrick's example seems to me to be
convincing evidence that is a questionable style, but there are other
reasons to question it. What does writing macros that way really buy
you? The macro can only do the most simple kinds of side-effect
analysis, it certainly can't do anywhere near as good a job as the
compiler; especially if the macro is intended to be portable.
The change you are proposing we make entrenches this bad style. It will
require implementors and users to edit each of their macros which does
the kind of optimization Patrick presents to respect symbol macros.
The change I am proposing is that we declare that macros should expand
without attempting to do any kind of optimizations based on side-effect
analysis. (Specifically that with-slot may be implemented in terms of a
simple code-walker). This will require editing the exact same set of
macros as the change you propose, but I believe it is a better solution
because:
1. It is more elegant. As I have said, I think it is bad style to
for macros do do optimizations based on side-effect analysis.
2. It is a simpler change to the language. Adding symbol macros to
the language as you suggest is a large and no doubt controversial
change.
3. People can start fixing their code right away. We can say right
now, getting the X3J13 committee to agree of course, that it is
bad style to implement macros which try to do this kind of side
effect analysis. Users and implementors can start fixing their
code right away, they don't need to wait until we spec out symbol
macros and get them added to the language, and all the
implementations.
∂30-Nov-86 1759 Gregor.pa@Xerox.COM initialization protocol strawman
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Nov 86 17:59:48 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 NOV 86 17:59:50 PST
Date: 30 Nov 86 17:57 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: initialization protocol strawman
To: Common-Lisp-Object-System@Sail.Stanford.edu
cc: Gregor.pa@Xerox.COM
Message-ID: <861130-175950-1032@Xerox>
Here is an initialization protocol proposal for people to shoot at. The
major characteristic of this protocol is its simplicity. This protocol
does not have support for automatic processing of make-instance keyword
arguments, this means that options like :initable-slots, :init-keywords
and :default-init-plist are not present in this proposal. Later in this
message I discuss why I think those are not needed.
make-instance <class> &rest <options> [generic function]
make instance is a generic function which has two "standard defined"
methods. Those methods look like:
(defmethod make-instance ((class-name symbol) &rest options)
(apply 'make-instance (class-named class-name) options))
(defmethod make-instance ((class class) &rest options)
(let ((instance (make-instance-internal class)))
.. code to initialize the slots from ..
.. the initforms (or whatever) in the ..
.. defclass form ..
(apply 'initialize instance options)
instance))
initialize <instance> &rest <options> [generic-function]
initialize is also a generic function, it has one "standard defined"
method. That method looks like:
;;
;; Notice the little idiom in the argument list here. You aren't
;; allowed to say &allow-other-keys unless you have said &key, but
;; you don't want to add some new keyword like :ignore or something.
;; So you say (&key allow-other-keys &allow-other-keys)
;;
(defmethod initialize ((o object) &key allow-other-keys
&allow-other-keys)
(declare (ignore allow-other-keys))
o)
So, make-instance can be used with a class which is an instance of class
or a subclass of class to make instances and call initialize as shown.
Initialize receives the newly created instance with its slots
initialized to the values supplied in the initforms given in the
defclass. Initialize can process the keywords and values it receives to
change the values of some of these slots, initialize slots whose values
were not specified in the defclass form, or do any other required
initialization.
In order for all initialize methods to have congruent lambda lists, they
must all have a required first argument, then possibly an &rest
argument, then keyword arguments. They must all specify
&allow-other-keys. The following are examples of legal initialize
methods:
(defmethod initialize ((b boat) &key speed
&allow-other-keys)
..)
(defmethod initialize ((b boat) &key allow-other-keys
&allow-other-keys)
(declare (ignore allow-other-keys))
(register b))
(defmethod initialize ((b boat) &rest options
&key speed
&allow-other-keys)
..)
Why is :initable-slots not needed?
Initable-slots provides the user with an automatic mechanism for
initializing the values of some of the slots from keyword-value pairs
supplied to make instance rather than the initforms in the defclass.
This is convenient in some cases, but it ends up with a multiplicity of
functionality which is not really needed, and which ends up being
complicated. Specifically, it means that when the user calls
make-instance, the value of the slots of the instance can come from one
of 4 places:
the initform in the defclass
a keyword-value pair in the call to make-instance
a keyword-value pair in the :default-init-plist
the user-defined initialize method
It is easy enough for the definer of a particular class to define an
initialize method which will take care of initializing slot values from
the &rest argument to make-instance that I see no need for the automatic
mechanism provided by :initable-slots.
:init-keywords is not needed because it is just an accessory to
:initable-slots
Why is :default-init-plist not needed?
If we have :around (or whopper) methods in the standard, as we plan to,
users can implement a similar behavior themselves.
∂30-Nov-86 2126 LGD new functions.* files on SAIL
To: common-lisp-object-system@SAIL.STANFORD.EDU
I have placed our new versions of the Functions section out on [CLS,LSP].
Files are functi.tex, functi.dvi, etc. There is a version with stripped
down fonts, symfun.dvi, to placate Symbolics' printers.
This part of the spec incorporates the results of our recent discussions
here on the west coast and our understanding of recent exchanges on this
mailing list.
Linda
∂01-Dec-86 1100 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: :accessor-prefix questions
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 1 Dec 86 11:00:49 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 12120; Mon 1-Dec-86 13:58:26 EST
Date: Mon, 1 Dec 86 13:58 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: :accessor-prefix questions
To: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <861130-123821-5477@Xerox>
Message-ID: <861201135811.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 30 Nov 86 12:38 PST
From: Masinter.pa@Xerox.COM
I want to advocate a requirement, but the requirement isn't exactly as
stated. The requirement is that the packages of the accessors depend
only upon information explicitly available within the defining form once
the defining form has been read. With current DEFSTRUCT, the package of
generated accessors depends on the value of *package* at the time the
DEFSTRUCT is evaluated, rather than at the time the DEFSTRUCT is read.
However, for every other definitional form in Common Lisp, the only
dependence on *package* (and other read-environment variables such as
*read-base*) is only on the value at read time.
This requirement can be satisfied either by making the accessor names
the same as the slot names, or by making the accessor names be interned
into the *same* package as the slots.
The latter was tried and found not to work. In retrospect it should have
been obvious. What if you have a slot named STRING? The accessor, say
FOO-STRING, can't go into the LISP package, because either it's exported from
LISP and thus causes all symbols named FOO-STRING unexpectedly to share with
each other, or it isn't exported from LISP and so the program that defined
it can't get at it.
The only way that I know of that works, assuming no changes to the package
feature as Common Lisp currently defines it, is for
(defclass foo () (string) (:accessor-prefix foo-))
to be defined to be equivalent to
(defclass foo () ((string :accessor foo-string)))
at the level of printed representations (rather than objects).
This is required, for example, in residential environments where the
time of evaluation of a definitional form might be different than the
time that form was READ.
I don't see how residential environments and file-based environments are
any different in this respect. All this means is that when you evaluate
something from program source, you have to evaluate it in the proper
context in which the program author put it. Maybe you didn't realize until
now that *package* is one of the variables that defines that context, but
surely it is easy to add.
It is good programming language design to keep
to a minimum the amount that the semantics of a given form depends upon
the dynamic environment and to separate out syntactic features from
semantic ones; *package* describes a syntactic feature rather than a
semantic one.
I agree with your comment on good programming language design, and I think
this reflects poorly on the design of Common Lisp packages. That shouldn't
be a surprise to anyone. In Common Lisp, *package* really is somewhat of
a semantic feature; it's not only syntactic.
∂01-Dec-86 1136 edsel!bhopal!jonl@navajo.stanford.edu :accessor-prefix questions
Received: from NAVAJO.STANFORD.EDU by SAIL.STANFORD.EDU with TCP; 1 Dec 86 11:36:19 PST
Received: by navajo.stanford.edu; Mon, 1 Dec 86 11:34:00 PST
Received: from bhopal.edsel.uucp by edsel.uucp (2.2/SMI-2.0)
id AA03993; Mon, 1 Dec 86 11:28:56 pst
Received: by bhopal.edsel.uucp (1.1/SMI-3.0DEV3)
id AA02053; Mon, 1 Dec 86 11:25:13 PST
Date: Mon, 1 Dec 86 11:25:13 PST
From: edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)
Message-Id: <8612011925.AA02053@bhopal.edsel.uucp>
To: navajo!Gregor.pa%Xerox.COM@navajo.stanford.edu
Cc: navajo!Common-Lisp-Object-System%SU-AI.ARPA@navajo.stanford.edu
In-Reply-To: Gregor Kiczales's message of 30 Nov 86 14:01 PST
Subject: :accessor-prefix questions
While I agree with your analysis about the inadvisibility of adding a
package argument to :conc-name, there is still an outstanding unsolved
problem (summed up yesterday by Masinter).
Namely, if the time of creation of the accessor symbols isn't the same as
the time of reading in the defining form, and the slot names, then how can
you insure that the accessors are "accessible from the same package" as was
current at read time? Unfortunately, Larry's suggestion
This requirement can be satisfied . . . by making the accessor names be
interned into the *same* package as the slots.
makes the very common error of assuming that a symbol is "interned" in
only one package ("THE *same* package"). If that were true, then one
would only have to find out what package the slot names are "interned" in
to find out what second argument to give to INTERN when constucting the
accessor symbols.
To illustrate the difficulty: Let FOO be "homed" in package BAR; also let
FOO be present and external in packages BAZ and BLETCH, both of which are
"used" by package CLASS-WORLD. Then some file which is IN-PACKAGE'd into
CLASS-WORLD will inherit (at read time!) the slot name FOO from BAZ and/or
BLETCH, *** neither of which is found in the symbol-package cell of FOO ***.
Furthermore, because of the possibility of shadowing, and of differing
inheritance links, it is entirely possible that even if <prefix>-FOO is
entered into the BAR package (the one in which FOO is "homed"), it will
still not be accessible when the current package is CLASS-WORLD. This would
certainly be counter to the intent of binding the package information in at
read time rather than at macro-expansion time.
Can Larry's requirement be met? Should it be? I think it can if a package
"slot" is maintained -- not one which the user could arbitrarily specify,
but one which reflects the "read time" binding of *package*.
-- JonL --
∂01-Dec-86 1326 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: portable interface to code walker
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 1 Dec 86 13:26:16 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 12339; Mon 1-Dec-86 16:20:04 EST
Date: Mon, 1 Dec 86 16:19 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: portable interface to code walker
To: Common-Lisp-Object-System@Sail.stanford.edu
In-Reply-To: <861130-173551-1018@Xerox>
Message-ID: <861201161950.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Sun, 30 Nov 86 20:35 EST
From: Gregor Kiczales <Gregor.pa@Xerox>
I have been thinking about Patrick's message for some time. I don't
believe the argument he is presenting about symbol-macros.
....
The change I am proposing is that we declare that macros should expand
without attempting to do any kind of optimizations based on side-effect
analysis.
I could give a long answer but I think a short one would be better. I don't
think is really an issue of optimizations. How do you propose that the
macro invocation (pushnew item (aref array (incf i))) should expand?
(If I've missed the point of what you're trying to say, please let me know.)
∂01-Dec-86 1613 Gregor.pa@Xerox.COM Re: portable interface to code walker
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Dec 86 16:13:33 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 01 DEC 86 15:55:58 PST
Date: 1 Dec 86 15:55 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: portable interface to code walker
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 1 Dec 86 16:19 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <861201-155558-2029@Xerox>
Date: Mon, 1 Dec 86 16:19 EST
From: David A. Moon
I could give a long answer but I think a short one would be
better. I don't think is really an issue of optimizations. How do
you propose that the macro invocation:
(pushnew item (aref array (incf i)))
should expand?
(let ((#:g01 item)
(#:g02 array)
(#:g03 (incf i)))
(aset (adjoin #:g01 (aref #:g02 #:g03)) #:g02 #:g03)))
Which seems to me to be the simplest way it could possibly expand. The
pushnew just assumes that evaluating the arguments to the <place> form
has side-effects so it makes certain to only evaluate them once. The
same way it assumes that evaluating the <item> form has side-effects and
only evaluates it once.
(If I've missed the point of what you're trying to say, please
let me know.)
I think you may have, but maybe the answer to your above question
clarifies it. Basically, my general point is that macros and compiler
optimizers should be kept separate. In this specific case, because some
macro definitions (pushnew in Patrick's example) try to optimize their
expansion based on side-effect analysis they will have to be re-written
to work with with-slots.
This is not to say that the implementation of a macro must not consider
the possibilityt of side effects. Of course it must to implement its
semantics properly. Its just that macros should leave optimization to
the compiler.
∂01-Dec-86 1850 Bobrow.pa@Xerox.COM Re: Class precedence list, underconstrained method ordering
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Dec 86 18:50:43 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 01 DEC 86 18:50:29 PST
Date: 1 Dec 86 18:50 PST
Sender: Bobrow.pa@Xerox.COM
Subject: Re: Class precedence list, underconstrained method ordering
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sat, 22 Nov 86 00:20 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SU-AI.ARPA,
KMP@STONY-BROOK.SCRC.Symbolics.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861201-185029-2210@Xerox>
I suspect this issue may be what some of Danny's class
precedence suggestions were really about, although he didn't phrase
them this way.
Yes, I was trying to avoid underconstraint. To restate the rules I
think are appropriate, they are (slightly edited from my message of 20
October):
The class precedence list is a left to right, depth first linearization
of the transitive closure of inheritance from the local super classes of
a class. It satisfies three constraints:
C-1) A class appears only once on the list.
C-2) The order of classes in a local supers list is preserved
C-3) A class always precedes all classes in its local supers list
It can be thought of as constructed as follows:
1) Walk the inheritance tree in left to right depth
first order, recording all super classes in the order visited.
2) Remove duplicates, preserving the last occurrence
of any class. This can be combined with step 1
without extra consing. This ensures that C-1 is satisfied.
In
most cases C-2 and C-3 will also be satisfied. This is true
for
all the examples in the Concepts document.
3) Traverse the resulting list from left to right. If
for any class c1, there is a class to its right that c1 should
follow, move c1 to the right of the rightmost such class.
This righmost class must be computed by recursive application of
rules C-2 and C-3. In computing this recursive dependency,
a dependency loop may be discovered, indicating an error.
This algorithm gives a well defined order in which all internal
superclasses of class-1 will precede all internal superclasses of
class-2 if there is no intersection. I propose we substitute the above
description for the one currently in CONCEP.
I don't think we want to deal with the following more global case.
(DEFCLASS american-apple-pie (apple pie))
(DEFCLASS french-apple-pie (pie apple))
I take it that this is what Moon's humble pie example is about.
Examples:
No intersection
(DEFCLASS1 C1 ())
(DEFCLASS1 C2 ())
(DEFCLASS1 D1 (C1))
(DEFCLASS1 D2 (C2))
(DEFCLASS1 E1 (D1 D2))
After Steps 1 and 2
(E1 D1 C1 D2 C2)
Simple Intersection:
(DEFCLASS1 C1 (OBJECT))
(DEFCLASS1 C2 (OBJECT))
(DEFCLASS1 D1 (C1))
(DEFCLASS1 D2 (C2))
(DEFCLASS1 E1 (D1 D2))
After Steps 1 and 2
(E1 D1 C1 D2 C2 OBJECT)
Moving Required:
(DEFCLASS1 C1 ())
(DEFCLASS1 C2 ())
(DEFCLASS1 C3 ())
(DEFCLASS1 D1 (C1 C2))
(DEFCLASS1 D2 (C1 C3))
(DEFCLASS1 E1 (D1 D2))
After Steps 1 and 2
(E1 D1 C2 D2 C1 C3)
In step 3, C2 must be moved after C1.
resulting in
(E1 D1 D2 C1 C2 C3)
Simple Error:
(DEFCLASS1 C2 ())
(DEFCLASS1 C3 ())
(DEFCLASS1 D4 (C3 C2))
(DEFCLASS1 D5 (C2))
(DEFCLASS1 D6 (C3 C2 D5 D4))
After steps 1 and 2:
(D6 D5 D4 C3 C2)
Now D5 needs to after C2 from D6 defintion. Computing the recursive
closure of the constraints on D5, we see that C2 must be after D4 from
D4, and D4 must be after D5 from D6!!! Error.
Complex Constraint
(DEFCLASS1 E1 (C1))
(DEFCLASS1 E2 (C2))
(DEFCLASS1 E3 (C3))
(DEFCLASS1 E4 (E3 E2 E1))
(DEFCLASS1 E5 (C1 C2))
(DEFCLASS1 E6 (C2 C3))
(DEFCLASS1 E7 (E5 E6 E4))
After Steps 1 and 2
(E7 E5 E6 E4 E3 C3 E2 C2 E1 C1)
In Step 3
C3 has to be after C2 from E6, and hence after C1 from E5, giving
(E7 E5 E6 E4 E3 E2 C2 E1 C1 C3)
Now C2 is next in the list and it moves past C1 from E5, giving
(E7 E5 E6 E4 E3 E2 E1 C1 C2 C3).
-- danny
∂02-Dec-86 1316 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: portable interface to code walker
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 2 Dec 86 13:16:46 PST
Received: from ti-csl by csnet-relay.csnet id bk26924; 2 Dec 86 15:26 EST
Received: from Jenner (jenner.ARPA) by tilde id AA08409; Tue, 2 Dec 86 08:16:09 cst
To: David A Moon <Moon@SCRC-STONY-BROOK.ARPA>
Cc: Common-Lisp-Object-System@SU-AI.ARPA
Subject: Re: portable interface to code walker
Date: 2-Dec-86 08:23:05
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2742906182@Jenner>
The names let-pseudo and symbol-let don't appeal to me; somehow they
don't seem to convey the semantics clearly. Symbolics Common Lisp has
something similar, called "symbol-macros", so the name "symbol-macrolet"
is my suggestion. This conveys the idea that it is similar to macrolet
but substitutes for symbols rather than for macro invoking lists.
I don't have any problem with the name "symbol-macrolet".
Do you want to propose symbol-macros (If I understand correctly, it is
a global version of symbol-macrolet) along with symbol-macrolet as an
extension to Common Lisp?
Patrick.
∂02-Dec-86 1338 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: portable interface to code walker
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 2 Dec 86 13:36:16 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 13648; Tue 2-Dec-86 16:33:24 EST
Date: Tue, 2 Dec 86 16:33 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: portable interface to code walker
To: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
cc: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <DUSSUD.2742906182@Jenner>
Message-ID: <861202163307.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 2-Dec-86 08:23:05
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
The names let-pseudo and symbol-let don't appeal to me; somehow they
don't seem to convey the semantics clearly. Symbolics Common Lisp has
something similar, called "symbol-macros", so the name "symbol-macrolet"
is my suggestion. This conveys the idea that it is similar to macrolet
but substitutes for symbols rather than for macro invoking lists.
I don't have any problem with the name "symbol-macrolet".
Do you want to propose symbol-macros (If I understand correctly, it is
a global version of symbol-macrolet) along with symbol-macrolet as an
extension to Common Lisp?
I do not. Symbol-macrolet can be implemented by a code-walker, with no
changes to the interpreter and compiler, but define-symbol-macro has
to be implemented directly, since Common Lisp doesn't provide a way for
the user to supply a function that walks over every piece of code everywhere.
Define-symbol-macro is also less useful.
∂02-Dec-86 1631 Gregor.pa@Xerox.COM code for compute-class-precedence-list
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Dec 86 16:28:18 PST
Received: from Semillon.ms by ArpaGateway.ms ; 02 DEC 86 16:12:05 PST
Date: Tue, 2 Dec 86 16:11 PST
From: Gregor.pa@Xerox.COM
Subject: code for compute-class-precedence-list
To: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <861202161119.4.GREGOR@AVALON.isl.parc.xerox.com>
Line-fold: no
Here is the code and some examples for the latest version of
compute-class-precedence-list as described by Danny yesterday.
At the end are some examples.
(DEFMACRO DEFCLASS1 (NAME SUPERCLASSES)
`(progn (setf (get ',name 'supers) ',superclasses)))
(defun compute-class-precedence-list (root)
(let ((cpl ())
(must-precede-alist ()))
;; We start by computing two values.
;; CPL
;; The depth-first left-to-right up to joins walk of the supers tree.
;; MUST-PRECEDE-ALIST
;; An alist of the must-precede relations. The car of each element of the
;;; must-precede-alist is a class, the cdr is all the classes which must
;; precede that class in the CPL.
;;
;; Note that the actual walk is breadth-first, right-to-left.
;;
(labels ((walk-supers (class &optional precedence)
(let ((elem (assoc class must-precede-alist)))
(if elem
(setf (cdr elem) (union (cdr elem) precedence))
(push (cons class precedence) must-precede-alist)))
(let* ((rsupers (reverse (cons class (get class 'supers))))
(precedence (cdr rsupers)))
(do ((sup rsupers (cdr sup))
(pre precedence (cdr pre)))
((null pre))
(walk-supers (car sup) pre)))
(unless (member class cpl) (push class cpl)))
(must-move-p (element list &aux move)
(dolist (must-precede (cdr (assoc element must-precede-alist)))
(when (setq move (member must-precede (cdr list)))
(return move))))
(find-farthest-move (element move)
(let ((closure (compute-must-precedes-closure element)))
(dolist (must-precede closure)
(setq move (or (member must-precede move) move)))
move))
(compute-must-precedes-closure (class)
(let ((closure ()))
(labels ((walk (element path)
(when (member element path)
(class-ordering-error
root element path must-precede-alist))
(dolist (precede (cdr (assoc element must-precede-alist)))
(pushnew precede closure)
(walk precede (cons element path)))))
(walk class nil)
closure))))
(walk-supers root) ;Do the walk
;; For each class in the cpl, make sure that there are no classes after it which
;; should be before it. We do this by cdring down the list, making sure that for
;; each element of the list, none of its must-precedes come after it in the list.
;; If we find one, we use the transitive closure of the must-precedes (using
;; find-farthest-move) to see where the class must really be moved. We use a
;; hand-coded loop so that we can splice things in and out of the CPL as we go.
(let ((tail cpl)
(element nil)
(move nil))
(loop (when (null tail) (return))
(setq element (car tail)
move (must-move-p element tail))
(cond (move
(setq move (find-farthest-move element move))
(setf (cdr move) (cons element (cdr move)))
(setf (car tail) (cadr tail));OK to use Interlisp delete trick since it
(setf (cdr tail) (cddr tail));will never be the last element of the list.
)
(t
(setq tail (cdr tail)))))
(copy-list cpl)))))
(defun class-ordering-error (root element path must-precede-alist)
(declare (ignore root))
(setq path (cons element (reverse (member element (reverse path)))))
(let ((explanations ()))
(do ((tail path (cdr tail)))
((null (cdr tail)))
(let ((after (cadr tail))
(before (car tail)))
(if (member after (get before 'supers))
(push (format nil "~% ~A must precede ~A -- ~A is in the local supers of ~A."
before after after before)
explanations)
(dolist (common-precede (intersection
(cdr (assoc after must-precede-alist))
(cdr (assoc before must-precede-alist))))
(when (member after (member before (get common-precede 'supers)))
(push (format nil "~% ~A must precede ~A -- ~A has local supers ~S."
before after
common-precede
(get common-precede 'supers))
explanations))))))
(error "While computing the class-precedence-list for the class ~A:~%~
There is a circular constraint through the classes:~{ ~A~}.~%~
This arises because:~{~A~}"
root path (reverse explanations))))
;;;; Examples
(defclass1 o ())
(defclass1 b1 (o))
(defclass1 b2 (o))
(defclass1 b3 (o))
(defclass1 b4 (o))
(defclass1 ex1-1 (b1 b3 b4))
(defclass1 ex1-2 (b2 b3))
(defclass1 example-1 (ex1-1 ex1-2))
(equal (compute-class-precedence-list 'example-1)
'(EXAMPLE-1 EX1-1 B1 EX1-2 B2 B3 B4 O))
(defclass1 o ())
(defclass1 b1 (o))
(defclass1 b2 (o))
(defclass1 b3 (o))
(defclass1 ex2-1 (b1))
(defclass1 ex2-2 (b2))
(defclass1 ex2-3 (b3))
(defclass1 example-2 (ex2-1 ex2-2 ex2-3))
(equal (compute-class-precedence-list 'example-2)
'(EXAMPLE-2 EX2-1 b1 EX2-2 b2 EX2-3 b3 O))
(DEFCLASS1 C1 ())
(DEFCLASS1 C2 ())
(DEFCLASS1 C3 ())
(DEFCLASS1 C4 (C1 C2))
(DEFCLASS1 C5 (C3 C2))
(DEFCLASS1 C6 (C4 C5))
(equal (compute-class-precedence-list 'c6)
'(C6 C4 C1 C5 C3 C2))
(DEFCLASS1 E1 (c1))
(DEFCLASS1 E2 (c2))
(DEFCLASS1 E3 (c3))
(DEFCLASS1 E4 (E3 E2 E1))
(DEFCLASS1 E5 (c1 c2))
(DEFCLASS1 E6 (c2 c3))
(DEFCLASS1 E7 (E5 E6 E4))
(equal (compute-class-precedence-list 'e7)
'(e7 e5 e6 e4 e3 e2 e1 c1 c2 c3))
(defclass1 d0 ())
(defclass1 d1 ())
(defclass1 d2 ())
(defclass1 d3 ())
(defclass1 e (d0 d1))
(defclass1 f (d1 d2 d3))
(defclass1 g (d1 d2))
(defclass1 h (d0))
(defclass1 foo (e f g h))
(equal (compute-class-precedence-list 'foo)
'(foo e f g h d0 d1 d2 d3))
(DEFCLASS1 D1 ())
(DEFCLASS1 D2 ())
(DEFCLASS1 D3 ())
(DEFCLASS1 D4 (D3 D2))
(DEFCLASS1 D5 (D2))
(DEFCLASS1 D6 (D3 D2 D5 D4))
(COMPUTE-CLASS-PRECEDENCE-LIST 'D6) ;should error
(defclass1 g1 ())
(defclass1 g2 ())
(defclass1 g3 ())
(defclass1 g4 ())
(defclass1 g5 (g1 g2))
(defclass1 g6 (g2 g3))
(defclass1 g7 (g3 g4))
(defclass1 g8 (g4 g5 g6 g7))
(compute-class-precedence-list 'g8) ;should error
-------
∂02-Dec-86 1921 Bobrow.pa@Xerox.COM Re: :accessor-prefix questions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Dec 86 19:21:28 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 02 DEC 86 18:38:48 PST
Date: 2 Dec 86 18:39 PST
Sender: Bobrow.pa@Xerox.COM
Subject: Re: :accessor-prefix questions
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 28 Nov 86 19:16 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SU-AI.ARPA
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Message-ID: <861202-183848-3396@Xerox>
With :accessor-prefix and :reader-prefix, how does one
specify that the accessor name is to be the same as the slot
name? A prefix of "" won't work, since that re-interns the
accessor name in the current package. Do we need two more
options for this? Should we treat the symbol NIL as a special
case? I think two more options would be more tasteful.
I still think additional options would be more tasteful than
treating NIL, or anything else, as a special case.
I prefer allowing either:
(:accessor-prefix) with no prefix specified
or
:accessor-prefix with no parens
to mean use the same symbol for the accessor as for the slot-name. I
find the first more "mnemonic" but could be argued out of it.
I shamefacedly admit that I never realized that allowing
strings would introduce a problem with alphabetic case. Consider
the plight of people who write their source code in lower case;
they would have to upper-case the string. Danny notwithstanding, I
think this makes it clear that strings should not be allowed here.
Even the null string should have to be written || rather than "".
With this new realization, I agree. But with the option specified
above, || would mean to reintern in the current package.
With this, I think an appropriate summary of the current allowed syntax
is:
(:accessor-prefix {symbol})
(:reader-prefix {symbol})
where if symbol is omitted, no new interning is done.
-- danny
∂03-Dec-86 2126 Moon@STONY-BROOK.SCRC.Symbolics.COM Comments on the revised function chapter
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 3 Dec 86 21:25:41 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 14942; Thu 4-Dec-86 00:24:01 EST
Date: Thu, 4 Dec 86 00:23 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Comments on the revised function chapter
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861204002343.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
These comments apply to the draft dated Nov 30, 1986 21:10.
The chapter title still calls it a user interface, even though what it
is actually documenting is a programmer interface.
The introduction section needs to be written (right now it only contains
one sentence). It should explain how the functions described in this
chapter fit into the overall scheme of things, including the relation
between the basic programmer interface and the meta-objects.
The functions ARGUMENT-PRECEDENCE-ORDER, GENERIC-FUNCTION-LAMBDA-LIST,
GENERIC-FUNCTION-METHOD-COMBINATION-TYPE, and LAMBDA-LIST-SPECIALIZERS are
unnecessary and should be removed. Perhaps they are really part of the
meta-object interface, but they aren't useful by themselves.
ADD-METHOD, DOCUMENTATION, GENERIC-FUNCTION-LAMBDA-LIST,
GENERIC-FUNCTION-METHOD-COMBINATION-TYPE, GET-METHOD, and REMOVE-METHOD
accept an argument that can be "a generic function or a symbol that names a
generic function." I thought we agreed in October that these functions
would also accept a list (SETF symbol) as a name of a setf generic
function. Looking back through the mail, I see Gregor agreeing on 21
Oct, Bobrow agreeing on 20 Oct, and me proposing it on 17 Oct. I didn't
see any other discussion; did I miss some mail?
The new term "method combination identifiers" was introduced for what
we used to call "method qualifiers" without any discussion. I'm not sure
and it's an improvement and I think there ought to be some discussion.
I don't like the presentation of options with a bullet followed by a
sentence containing somewhere the option name. People want the option
name to be first, and exdented to the left margin, so they can easily
find the description of an option. Also, the textual description of
options often refers to the arguments of an option with italicized words,
but these arguments are not defined locally; you have to go back to the
syntax section to find them. This is particularly bad in defclass, because
its writeup is so big. The previous version, which repeated the syntax
pattern of an option as a header on its textual description, was better.
Why do we have make-generic-function, make-instance, and make-method, but
no make-class?
Comments on specific functions:
ADD-METHOD:
Typo: 2nd para under arguments says "or with the lambda" when it means
"and with the lambda".
Typo: "argument specializers" should be "parameter specializers."
The values description is awkward. There has to be a simpler way to
phrase such a simple concept as side-effecting an object passed as
an argument and returning the same object.
Add-method was changed to signal an error if an equivalent method already
exists, instead of replacing it. There doesn't appear to be a way any more
to replace a method. I also don't see a way to update the definition of a
method while keeping the same method object. In the absence of such
facilities it's not very useful to document add-method.
CALL-NEXT-METHOD:
Typo: "may to be used" in 6th para under purpose.
Typo: first sentence in remarks is missing a comma before "affects".
This sentence would be clearer if it was amplified by adding a second
sentence: "Call-next-method passes the current method's original arguments
along to the next method." This was already said under purpose, so what
we are really seeing here is the bad effect of the decision to split the
presentation of information arbitrarily among "purpose", "arguments", and
"remarks" sections. In many cases this document is unnecessarily difficult
to read because sentences that should be in the same paragraph have been
moved into separate sections. I assume this can be improved in future drafts.
Inconsistent language: we say it "is used", "may be used", is "called from",
is "done in", and is "called with". The verb "used" seems the most
appropriate and should be used consistently.
CHANGE-CLASS:
Typo: first sentence says "the new class" when it means "a new class".
This seems to imply that the second argument is not allowed to be the
name of a class. Why not?
The remarks should clarify that not all objects will allow change-class.
For example, an implementation is not required to support change-class on
any built-in object. (I don't think implementations should be prohibited
from supporting it; some built-in classes in some implementations might be
implemented using the Class system rather than being implemented in a
primitive way.)
In Menlo Park we discussed restrictions on when change-class could be
called. They belong here. My notes from that meeting indicate that we
agreed on the general idea of the restrictions, but couldn't come up with a
good way of explaining it in the meeting, and said we should work on that
over the mail. The general idea was that if execution is inside of a
context in which the class of an object is declared lexically, e.g. inside
a method or inside a with-slots, then changing the class of that object
leaves the activation record of that context in "a wierd state", because of
early binding by compilers. The exact details of what "a wierd state"
means weren't worked out; one idea is that it is illegal to access a slot
of the object in that context after its class has been changed. When a
particular generic function invocation invokes multiple methods because of
method combination or because of call-next-method, all methods after the
one that changed the class are in "a wierd state"; this is necessary
because changing the class of an argument can change the set of available
methods, but implementations need to be free to bind that set at generic
dispatch time. In Flavors we have a more specific description of what the
user can rely on which might serve as a model.
DEFCLASS:
Clarification: Last sentence under Purpose should make it clear that
the object can be directly an instance of the new class or can be
directly an instance of a subclass of the new class. It's important
to be explicit since people tend to get confused easily on this point.
slot-name is not defined in the syntax figure.
We have not agreed on the name :initform yet; this needs discussion.
Something called :initialize-only was added without discussion. This
seems to be unnecessary and should be removed, although I'll be happy
to listen to reasons why it is useful and should stay if there are
some.
The :dynamic and :none allocation-types are hacks and should be removed.
In Menlo Park we spent a long time talking about the weirdness of
dynamic allocation, and my conclusion from that is that it doesn't
belong in the standard. I have no problems with :instance and :class
allocation.
The option :uninstantiable, formerly :instantiable, formerly :abstract is
of the same category as :required-flavors and does not belong in the
standard if the criterion is to omit merely protocol-enforcing options. It
should be removed (a good thing, since we still haven't found a decent
name for it!).
In the syntax for boa-arglists, supplied-p parameters should be allowed
since they can be used in initforms of later parameters. The description
of defstruct b.o.a. constructors in CLtL is too vague, but seems to imply
that supplied-p parameters are disallowed. CLtL doesn't allow &key and
&allow-other-keys in boa-arglists, but of course it should. They should
be allowed in defclass unless someone can present a good argument against
them. We have found them useful.
Under arguments, 2nd para, I don't think the remark about built-in classes
belongs here.
Typo: "the a generic" under :reader.
The description of :allocation :instance slot-option refers to storing the
variable in the class instance. To me this sounds the same as :allocation
:class. In general, when the terms "class object" and "class instance" are
thrown around it's very difficult to keep track of which is which.
Typo: "slot (storage)" under :allocation :class.
You forgot to say whether the :initialize-only and :type slot-options can
be given more than once.
Typo: "on generic function" under :accessor-prefix and :reader-prefix.
The vague word "processed" is used in the description of :accessor-prefix
and :reader-prefix. Use a more specific word. Do you mean evaluated or
macro-expanded? When compiling, do you mean compile time or load time?
I could go with either.
Some of the details of :accessor-prefix and :reader-prefix, especially
how you get it to use the slot names as the accessor names, are still
under discussion and what's in the document may change.
I couldn't think of a more confusing way to describe the :metaclass option
than the way it's described here. Maybe the concept is inherently
confusing, but I think we could do better. One suggestion is always and
consistently to use the word "metaclass" to refer to a class that is the
class of a class, and reserve the word "class" entirely for the set of
classes that are not metaclasses.
Remarks section: on redefining classes: I assume it is not permitted to
redefine a built-in class. Why is the temporary copy of class object
created when it is redefined given a name at all? Since when are we
redefining the Common Lisp EQUAL function? The fourth bullet would be
less confusing if it were rephrased in the singular.
The remark about slots that have not been initialized was weakened from the
previous version. You went too far; as written this would prohibit all
implementations from signalling an error when an uninitialized slot is
referenced, because legal programs could read the slot and discard its
value. Like it or not, we have to say "is an error" here.
The last sentence under remarks implies that the :allocation slot-option
can only be used in one slot-description in a defclass. This is not
what you meant to say! I would break this into two sentences: "No other
class option may appear more than once in a single defclass form. No
other slot-option may appear more than once in a single slot-description."
The relationship between accessors (methods created with :accessor, :reader,
:accessor-prefix, and :reader-prefix) and regular methods (created with
defmethod) needs to be discussed. One issue is how they combine, e.g.
(defmethod-setf foo-slot :after ((object foo)) (new-value) ...).
Another is what happens if you define a conflicting regular method, e.g.
(defmethod-setf foo-slot ((object foo)) (new-value) ...) when
(defclass foo () ((slot :accessor foo-slot))) has been done.
DEFGENERIC-OPTIONS:
I still think this choice of name reflects a fundamental misunderstanding,
but it won't be the first poorly chosen name in Common Lisp so I suppose
we can live with it if we have to. Having gotten that bit of steam off
my chest I can go on to substantive comments.
:argument-precedence-order should be changed back to the way it was in
the previous version. These positional numbers don't add any expressive
power and do add new ways to mess up.
declare option: the optimize declaration seems to have gotten lost in
editing. I would expect this to be the most useful declaration in most
implementations, except for very simple ones that won't do anything with
the advice because they have only one form of generic dispatching. The
reference to the FTYPE declaration doesn't make any sense; probably it is a
typo for TYPE declarations of parameters. If FTYPE was really intended,
I'm confused and some explanation and an example should be added.
DEFGENERIC-OPTIONS-SETF:
Typo: The second sentence under purpose says "generic-function-name" but
should say "name" to be consistent with the rest of the page.
The last sentence under arguments, about the setf-lambda-list, isn't really
true since no variables are getting bound here. The variable name is
really just documentation. I'd say this text was accidentally copied from
defmethod-setf, except that it doesn't appear there. Move it to there.
DEFMETHOD:
What happens if "name" currently names a non-generic function? For consistency
with defgeneric-options, defmethod should signal an error.
In the second para under purpose, the list of attributes for creating a
generic function is somewhat garbled. G.f.'s don't have parameter specializers.
Lambda-list and method-combination need to be mentioned.
In the last line under syntax, I would prefer (QUOTE datum) rather than 'datum.
Being explicit is always a good idea.
Typo: under arguments, "arguments, have t" should be "arguments have t".
The value returned by defmethod was changed from a method object, in the
previous version, to a rather hokey list. This was not discussed over the
mail unless I missed some mail. I think this should be changed back.
DEFMETHOD-SETF:
Typo: an asterisk in the syntax for specialized-setf-lambda-list
should be a right parenthesis.
Typo: The phrase "stuff?]" mysteriously appears under arguments.
I still don't like returning a hokey list instead of an object as the value.
DESCRIBE:
One method is enough, change "classes t and object" to "class t".
DOCUMENTATION:
In the first sentence under purpose, why does it say "class object"
but not "method object"? This is very confusing.
Why is documentation said to be generic? Are users supposed to write
methods for it?
I'm grossed out by the schizophrenia between documentation of symbols
and documentation of objects. Saying that if the first argument is
not a symbol, the second argument must be unsupplied would help a
little. It's still going to add new inconsistencies to Common Lisp;
consider that (DOCUMENTATION (SYMBOL-FUNCTION foo)) will work if
foo is the name of a generic function, but not if foo is the name of
a regular function. I would prefer for DOCUMENTATION to be left the
way it is, as an operation on names rather than an operation on objects.
If I do (SETF (SYMBOL-FUNCTION 'BAR) (SYMBOL-FUNCTION 'FOO)), do
occurrences of the string FOO in examples in the documentation
automatically get changed to BAR? I assume the reason someone is
proposing to change documentation to be object-oriented is because
Common Lisp is defective and doesn't have any names for methods, because
only symbols can be used as names. We could fix that.
GET-METHOD:
What happens if you ask for a default method when the symbol given as
the first argument names a non-generic function? Does it signal an error
or return a method object representing that function? The former would
seem to be more consistent with some other functions in this version of
the spec.
I've argued against this form of the specializers list before, so I won't
bore you by repeating my claims that doing it this way won't work well.
Please reread the mail.
MAKE-GENERIC-FUNCTION:
Under remarks it says this is the programmatic interface to defgeneric-options,
but in fact this function does not do the same thing. Defgeneric-options
can update an existing generic function.
I think some of the keyword arguments must be required. Which ones?
MAKE-INSTANCE:
Typo: "instance of class" should be "instance of a class"
Typo: :instantiable option was renamed (but I say it should be removed).
MAKE-METHOD:
I would think a method object would want to know what generic-function it
was for; another argument should be added. It at least wants to know this
for purpose of printing out.
What are the requirements on the function: arguments, results, and environment
for call-next-method? I prefer that only functions that have been blessed
by the generic-function meta-object before being compiled be allowed. I
suppose we could allow any function here with naive arguments, but then
we just have to have MAKE-METHOD-REAL, which is the one DEFMETHOD really
uses.
PRINT-OBJECT:
One method is enough, change "classes t and object" to "class t".
The arguments are an object and a stream; same as PRIN1 except that
the stream is not optional and cannot be T or NIL.
The value is the first argument (the object).
REMOVE-METHOD:
Typo: A sentence about argument list congruency was inadvertently
copied from add-method.
Value should be described the same way as add-method (after add-method's
value description is rewritten in English).
SLOT-VALUE:
What if no slot with that name exists? Does it signal an error, "is" an
error, or return something?
Do built-in objects have slots?
Can slot-value access defstruct slots?
WITH-SLOTS:
In the last sentence under purpose, "unless the value of the :use-accessors
argument is nil" should be "unless the :use-accessors argument is nil",
since this argument is not evaluated. In general it should be clarified
that none of the options in this special form are evaluated.
The first sentence under arguments doesn't make sense since everything
is an instance of a class.
Second para under arguments: "instance" in italics should be
"instance-form". What happens if the restriction discussed is
violated? Signal an error?
First bullet under arguments: Typo: "method form" should be
"method body".
Second bullet under arguments: hyphens at the end of the prefix
are used inconsistently. The vague word "processed" appears again
(see defclass).
There is a serious bug in WITH-SLOTS. Unlike DEFCLASS, which is
always used at top level and therefore is macroexpanded with a
predictable value of *PACKAGE*, interpreters that do not fully
macroexpand at the time DEFUN is evaluated, which CLtL permits,
will macroexpand WITH-SLOTS in an unpredictable dynamic environment
and therefore with an unpredictable value of *PACKAGE*. I have
two suggestions for fixing this, both fairly distasteful. One
is to document the bug and say that WITH-SLOTS with :PREFIX should
only be used in compiled code. The other is to eliminate the
:PREFIX option and say that cases that are so complicated should
just call the accessors explicitly.
Under examples, comments contrasting the two move methods that were
lost in earlier editing are still missing. The let should be removed
from the make-horizontal method since instance-forms can be any form,
and the indentation of this method should be corrected.
Some remarks that were present in the previous version seem to have
been lost in editing, unless the printer I used loses text from
the last page (nothing would surprise me!). The remarks were that
setq is allowed as well as setf, that it signals an error if the
class is not specified or implied, and that it signals an error if
pseudo-variable names clash.
Thank you for reading all 400 lines.
∂05-Dec-86 1035 Gregor.pa@Xerox.COM &key &allow-other-keys
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Dec 86 10:35:04 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 DEC 86 10:12:57 PST
Date: 5 Dec 86 10:12 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: &key &allow-other-keys
To: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <861205-101257-6043@Xerox>
When I sent out the initialization protocol the other day, I didn't
realize that you could have (&key &allow-others-keys) in a lambda list,
I thought you always had to have at least one keyword, this the idiom
(&key allow-other-keys &allow-other-keys). It seemed like a bug, but it
was the wat I interpreted it.
Anyways, everyplace where I put
(&key allow-other-keys &allow-other-keys)
should be (&key &allow-other-keys)
Any other comments on that proposed protocol?
∂06-Dec-86 0732 masinter.pa@Xerox.COM Re: :accessor-prefix questions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Dec 86 07:32:28 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 06 DEC 86 07:29:31 PST
Date: 6 Dec 86 07:29 PST
From: masinter.pa@Xerox.COM
Subject: Re: :accessor-prefix questions
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 1 Dec 86 13:58 EST
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861206-072931-1250@Xerox>
This proposal takes a bit of getting used to. Think about it a bit
before responding.
MOTIVATION:
Why do we want :accessor-prefix? Because it is a useful and interesting
shorthand to the more verbose and less ambiguous form of explicitly
giving the accessors.
(defclass foo () (string vector) (:accessor-prefix foo-))
Is clearly less verbose than
(defclass foo () ((string :accessor foo-string) (vector :accessor
vector-string)))
PROBLEM: (not repeated here)
PROPOSAL:
Here's an alternative that is not much more verbose, but reduces the
problem of the package of the accessors. Observation: the package of the
accessors is critical. The package of the slots is meaningless. So,
instead of *adding* the prefix, *remove it* when present, for the slot
name, e.g.
(defclass foo ()
(foo-string foo-vector)
(:accessor-prefix foo-))
this says that "foo-string" and "foo-vector" are accessors defined for
the slots "string" and "vector" respectively.
This even gives some selective control over which slots do and don't get
accessors.
With additive accessor-prefix, you get an accessor for *every* slot.
With subtractive accessor-prefix, you can avoid the accessor merely by
leaving off the prefix:
(defclass foo ()
(foo-string foo-vector widget)
(:accessor-prefix foo-))
This says that foo-string and foo-vector get accessors, but widget
doesn't.
In fact, you could (if you had featuritis) have multiple accessor
prefixes, e.g.
(defclass foo ()
(point-x point-y window-title window-place froboz)
(:accessor-prefix point- window-))
∂09-Dec-86 1722 Gregor.pa@Xerox.COM Re: Comments on the revised function chapter
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Dec 86 17:21:11 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 09 DEC 86 15:38:19 PST
Date: 9 Dec 86 15:38 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Comments on the revised function chapter
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 4 Dec 86 00:23 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861209-153819-3738@Xerox>
Date: Thu, 4 Dec 86 00:23 EST
From: David A. Moon
These comments apply to the draft dated Nov 30, 1986 21:10.
These are my comments on your comments. As usual, in the interest of
brevity, I have not included portions of your message to which I had
nothing to add.
ADD-METHOD, DOCUMENTATION, GENERIC-FUNCTION-LAMBDA-LIST,
GENERIC-FUNCTION-METHOD-COMBINATION-TYPE, GET-METHOD, and
REMOVE-METHOD accept an argument that can be "a generic function or
a symbol that names a generic function." I thought we agreed in
October that these functions would also accept a list (SETF symbol)
as a name of a setf generic function. Looking back through the
mail, I see Gregor agreeing on 21 Oct, Bobrow agreeing on 20 Oct,
and me proposing it on 17 Oct. I didn't see any other discussion;
did I miss some mail?
I agree with this. I suppose we just forgot to put it in. This is
related to specifying get-setf-generic-function and specifying what
defmethod-setf does with the new-value arguments, which both need to be
done.
I don't like the presentation of options with a bullet followed
by a sentence containing somewhere the option name.
I agree. I believe Linda agrees also. When she gets back from vacation
I think we can work something out which will be easier to read.
Why do we have make-generic-function, make-instance, and
make-method, but no make-class?
I believe make-class was left out because its interaction with named
classes is more complicated, and we must have thought it "belonged in
the meta-obect protocol" section. We need to specify make-class and put
in in chapter 1.
Comments on specific functions:
ADD-METHOD:
Add-method was changed to signal an error if an equivalent
method already exists, instead of replacing it. There doesn't
appear to be a way any more to replace a method. I also don't see
a way to update the definition of a method while keeping the same
method object. In the absence of such facilities it's not very
useful to document add-method.
I believe the appropriate fix for this is to make get-method return nil
when it can find the specified method. As far as updating the
definition of a method while keeping the same method object, we need to
decide if we want to allow setf of method-function of a method.
CHANGE-CLASS:
In Menlo Park we discussed restrictions on when change-class
could be called. They belong here. My notes from that meeting
indicate that we agreed on the general idea of the restrictions,
but couldn't come up with a good way of explaining it in the
meeting, and said we should work on that over the mail.
We should work out a clear description of what these restrictions are.
This restriction should probably be biased in the direction of the
implementor. Perhaps you should send out the description from flavors
as a start.
DEFCLASS:
Something called :initialize-only was added without discussion.
This seems to be unnecessary and should be removed, although I'll
be happy to listen to reasons why it is useful and should stay if
there are some.
This is just a renaming of the defstruct :read-only slot option. I
would be glad to remove this option.
The :dynamic and :none allocation-types are hacks and should be
removed. In Menlo Park we spent a long time talking about the
weirdness of dynamic allocation, and my conclusion from that is
that it doesn't belong in the standard. I have no problems with
:instance and :class allocation.
:dynamic and :none are not hacks. My recollection from Menlo Park is
that the concern was over undeclared dynamic slots not declared ones.
We spent some time talking about whether there should be some function
(perhaps get) which should create :dynamic slots on the fly. We weren't
sure about this. But I thought we all agreed that declared :dynamic
slots were reasonable.
The option :uninstantiable, formerly :instantiable, formerly
:abstract is of the same category as :required-flavors and does not
belong in the standard if the criterion is to omit merely
protocol-enforcing options. It should be removed (a good thing,
since we still haven't found a decent name for it!).
I agree.
In the syntax for boa-arglists, supplied-p parameters should be
allowed since they can be used in initforms of later parameters.
The description of defstruct b.o.a. constructors in CLtL is too
vague, but seems to imply that supplied-p parameters are
disallowed. CLtL doesn't allow &key and &allow-other-keys in
boa-arglists, but of course it should. They should be allowed in
defclass unless someone can present a good argument against them.
We have found them useful.
Yes, this is a deficiency in some Common Lisps defstruct. When this
section is expanded to say more than just (like in defstruct) this
should be put in.
The vague word "processed" is used in the description of
:accessor-prefix and :reader-prefix. Use a more specific word. Do
you mean evaluated or macro-expanded? When compiling, do you mean
compile time or load time? I could go with either.
I think macro-expanded would be best here. If course there are
proposals that would make this mute.
Some of the details of :accessor-prefix and :reader-prefix,
especially how you get it to use the slot names as the accessor
names, are still under discussion and what's in the document may
change.
See my comments on with-slots later in this message.
Remarks section: on redefining classes: I assume it is not
permitted to redefine a built-in class. Why is the temporary copy
of class object created when it is redefined given a name at all?
The copy of the class object created when it is redefined is given a
name so that users can define methods on change-class-using-class to
convert instances.
The remark about slots that have not been initialized was
weakened from the previous version. You went too far; as written
this would prohibit all implementations from signalling an error
when an uninitialized slot is referenced, because legal programs
could read the slot and discard its value. Like it or not, we have
to say "is an error" here.
We did this on purpose. I don't see why we have to say "is an error
here". Our thought was that a legal program could count on being able
to read the value of an unitialized slot, could count on the fact that
the value was a legal pointer, but could not count on what the value
was.
The relationship between accessors (methods created with
:accessor, :reader, :accessor-prefix, and :reader-prefix) and
regular methods (created with defmethod) needs to be discussed.
One issue is how they combine, e.g. (defmethod-setf foo-slot :after
((object foo)) (new-value) ...). Another is what happens if you
define a conflicting regular method, e.g. (defmethod-setf foo-slot
((object foo)) (new-value) ...) when (defclass foo () ((slot
:accessor foo-slot))) has been done.
Right. I believe the way to make this clear is to specify that the
accessor methods are regular methods, they behave as if they were
defined by a defmethod, e.g.
(defmethod foo-slot ((foo foo)) (slot-value foo 'slot))
DEFGENERIC-OPTIONS:
declare option: the optimize declaration seems to have gotten
lost in editing. I would expect this to be the most useful
declaration in most implementations, except for very simple ones
that won't do anything with the advice because they have only one
form of generic dispatching. The reference to the FTYPE
declaration doesn't make any sense; probably it is a typo for TYPE
declarations of parameters. If FTYPE was really intended, I'm
confused and some explanation and an example should be added.
I think the optimize declarations would be better handled by using a
different class of generic function. What optimize has over a different
class of generic function is that defgeneric-options with optimize
declarations in them would be portable even if many implementations
choose to ignore the declaration. I would be willing to put optimize
back.
FTYPE was mentioned explicitly because we thought (I think Dick
suggested this) that this would be a way to declare the argument/value
type behavior of the generic function as a whole. It was felt that in
some implementations (like Dick's) this might be very helpful.
DEFMETHOD:
The value returned by defmethod was changed from a method
object, in the previous version, to a rather hokey list. This was
not discussed over the mail unless I missed some mail. I think
this should be changed back.
Right, the list is hokey. It was changed away from the method object in
the interest of consistency with all the other DEFmumble forms which
return symbols ("names" actually). What if we just made it return the
generic-function-name?
DESCRIBE:
One method is enough, change "classes t and object" to "class
t".
See my comments under print-object later in this message.
DOCUMENTATION:
I'm grossed out by the schizophrenia between documentation of
symbols and documentation of objects.
I agree that this is all screwed up. Do you have another proposal?
GET-METHOD:
What happens if you ask for a default method when the symbol
given as the first argument names a non-generic function? Does it
signal an error or return a method object representing that
function? The former would seem to be more consistent with some
other functions in this version of the spec.
Signals an error.
MAKE-METHOD:
I would think a method object would want to know what
generic-function it was for; another argument should be added. It
at least wants to know this for purpose of printing out.
Our thought was that a method could be on more than one generic
function.
What are the requirements on the function: arguments, results,
and environment for call-next-method? I prefer that only functions
that have been blessed by the generic-function meta-object before
being compiled be allowed. I suppose we could allow any function
here with naive arguments, but then we just have to have
MAKE-METHOD-REAL, which is the one DEFMETHOD really uses.
As I said before, I don't believe the function should have to be
blessed. In the implementation I have in mind, we would not need to
bless the function and also not have to have make-method-real. I think
even for implementations which choose to have blessed functions it is a
misfeature to push this blessing in the user's face, it should be behind
the scenes.
PRINT-OBJECT:
One method is enough, change "classes t and object" to "class
t".
Shouldn't there be a method on t which prints with #<FOO 213213> syntax,
and a method on object whichs uses some readable syntax like #S(FOO A 1
B 3).
SLOT-VALUE:
What if no slot with that name exists? Does it signal an
error, "is" an error, or return something?
signals an error
Do built-in objects have slots?
Can slot-value access defstruct slots?
I have two opinions about this:
YES -- but this will require fleshing out the part in concepts that says
that defstruct defines classes.
NO -- since defstruct is going away anyways.
WITH-SLOTS:
There is a serious bug in WITH-SLOTS. Unlike DEFCLASS, which
is always used at top level and therefore is macroexpanded with a
predictable value of *PACKAGE*, interpreters that do not fully
macroexpand at the time DEFUN is evaluated, which CLtL permits,
will macroexpand WITH-SLOTS in an unpredictable dynamic environment
and therefore with an unpredictable value of *PACKAGE*. I have two
suggestions for fixing this, both fairly distasteful. One is to
document the bug and say that WITH-SLOTS with :PREFIX should only
be used in compiled code. The other is to eliminate the :PREFIX
option and say that cases that are so complicated should just call
the accessors explicitly.
I have a third solution. When there is a :prefix, intern the resulting
symbol in the package of the prefix. Theoretically, this has exactly
the same problems as the proposal to make defclass intern accessors in
the package of the slot-name. But I believe this will be MUCH less
likely to happen since prefixes usually end in -, and people don't
usually export symbols which end in -. This is what PCL does now.
In fact, we might want to think about doing this to defclass as well.
Some remarks that were present in the previous version seem to
have been lost in editing, unless the printer I used loses text
from the last page (nothing would surprise me!). The remarks were
that setq is allowed as well as setf, that it signals an error if
the class is not specified or implied, and that it signals an error
if pseudo-variable names clash.
Right, these need to be put back.
Thank you for reading all 400 lines.
You're welcome.
∂12-Dec-86 1450 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: :accessor-prefix questions
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 12 Dec 86 14:49:55 PST
Received: from ti-csl by csnet-relay.csnet id ah19978; 12 Dec 86 8:45 EST
Received: from Jenner (jenner.ARPA) by tilde id AA01229; Tue, 9 Dec 86 14:07:55 cst
To: masinter.pa@XEROX.COM
Cc: Common-Lisp-Object-System@SU-AI.ARPA
Subject: Re: :accessor-prefix questions
Date: 9-Dec-86 10:44:45
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2743519482@Jenner>
Observation: the package of the
accessors is critical. The package of the slots is meaningless. So,
instead of *adding* the prefix, *remove it* when present, for the slot
name, e.g.
I don't agree with this observation, the package of the slots matters
because we have WITH-SLOTS.
(defclass file ()
(file-author file-length file-position)
(:accessor-prefix file-))
(with-slots ((object :class file))
(assert (< position length))) ;We need to know the right name for those
;(that is pname & package).
It seems to me then that this proposal has the same flaws the other one has.
Please tell me if I missed your point.
Patrick.
∂12-Dec-86 1911 Bobrow.pa@Xerox.COM Re: Comments on the revised function chapter
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 12 Dec 86 19:01:01 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 12 DEC 86 18:24:59 PST
Date: 12 Dec 86 18:24 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Comments on the revised function chapter
In-reply-to: Gregor Kiczales <Gregor.pa>'s message of 9 Dec 86 15:38 PST
To: Gregor.pa@Xerox.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM,
Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861212-182459-1721@Xerox>
ADD-METHOD, DOCUMENTATION, GENERIC-FUNCTION-LAMBDA-LIST,
GENERIC-FUNCTION-METHOD-COMBINATION-TYPE, GET-METHOD, and
REMOVE-METHOD accept an argument that can be "a generic
function or a symbol that names a generic function." I thought
we agreed in October that these functions would also accept a
list (SETF symbol) as a name of a setf generic function.
Looking back through the mail, I see Gregor agreeing on 21 Oct,
Bobrow agreeing on 20 Oct, and me proposing it on 17 Oct. I
didn't see any other discussion; did I miss some mail?
I agree with this. I suppose we just forgot to put it in.
This is related to specifying get-setf-generic-function and
specifying what defmethod-setf does with the new-value arguments,
which both need to be done.
The function (get-generic-function-setf symbol) should return the setf
generic function. All those methos that require a setf generic function
should be called with that object, rather than a list. Given this, we
could (arghh) define an ADD-METHOD etc method on CONS that checks if the
argument is of the form (SETF symbol)....
Note: my spelling get-generic-function-setf is different than Gregor's
get-setf-generic-function. It obeys the rule that all "setf" morphs
appear at the end, though it doesn't read in English as well. What
should we use???
... what defmethod-setf does with the new-value arguments.
I thought we decided (you told me) that it had to go at the beginning to
allow optionals etc. What issue remians.
Add-method was changed to signal an error if an
equivalent method already exists, instead of replacing it.
There doesn't appear to be a way any more to replace a method.
I also don't see a way to update the definition of a method
while keeping the same method object. In the absence of such
facilities it's not very useful to document add-method.
I believe the appropriate fix for this is to make get-method
return nil when it can find the specified method. As far as
updating the definition of a method while keeping the same method
object, we need to decide if we want to allow setf of
method-function of a method.
should read "get-method return nil when it CANNOT find the specified
method" I also believe it is better to have replacement semantics for
ADD-METHOD, as suggested by Moon. With this, I don't see any compelling
argument for allowing methods to be updated, and can se serious
technical problems if we allow the user to replace the function of the
method in terms of checking arguments.
Something called :initialize-only was added without
discussion. This seems to be unnecessary and should be
removed, although I'll
be happy to listen to reasons why it is useful and
should stay if there are some.
This is just a renaming of the defstruct :read-only slot
option. I would be glad to remove this option.
I agree also, but it brings up the issue of what we do with old
DEFSTRUCTS if we take seriously the idea of replacing them with DEFCLASS
and DEFRECORD if not all feautres are supported.
The option :uninstantiable, formerly :instantiable,
formerly :abstract is of the same category as :required-flavors
and does not belong in the standard if the criterion is to omit
merely protocol-enforcing options. It should be removed (a
good thing, since we still haven't found a decent name for it!).
I agree.
I sadly agree as well.
DEFMETHOD:
The value returned by defmethod was changed from a
method object, in the previous version, to a rather hokey list.
This was not discussed over the mail unless I missed some
mail. I think this should be changed back.
Right, the list is hokey. It was changed away from the method
object in the interest of consistency with all the other DEFmumble
forms which return symbols ("names" actually). What if we just
made it return the generic-function-name?
I see no good argument for maintianing consistency in this case
(Consistency is the hobgoblin of small minds, it is said) and it would
be much more useful to have the object.
DOCUMENTATION:
I'm grossed out by the schizophrenia between
documentation of symbols and documentation of objects.
I agree that this is all screwed up. Do you have another
proposal?
Is documentation only supposed to be associated with named objects?
Isn't it in the spirit of object oriented programming to have methods
that do the appropriate thing for diferent types. Explain more about
your sense of craziness.
SLOT-VALUE:
Can slot-value access defstruct slots?
YES since they are translated into DEFCLASSes.
I won't be back again till Wednesday, Dec 17. Dallas was a good meeting
to miss if you had to miss one. Technical discussion was held to a
minimum. It snowed on Thursday night. Some useful political things
were done though(formalization of subcommittees is one).
danny
∂13-Dec-86 0915 skeene@STONY-BROOK.SCRC.Symbolics.COM restrictions on change-class
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 13 Dec 86 09:13:53 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 21936; Fri 12-Dec-86 10:01:18 EST
Date: Fri, 12 Dec 86 10:01 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: restrictions on change-class
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861212100117.4.SKEENE@JUNCO.SCRC.Symbolics.COM>
From a message by Moon:
"In Menlo Park we discussed restrictions on when change-class could be
called. They belong here. My notes from that meeting indicate that we
agreed on the general idea of the restrictions, but couldn't come up with a
good way of explaining it in the meeting, and said we should work on that
over the mail. The general idea was that if execution is inside of a
context in which the class of an object is declared lexically, e.g. inside
a method or inside a with-slots, then changing the class of that object
leaves the activation record of that context in "a wierd state", because of
early binding by compilers. The exact details of what "a wierd state"
means weren't worked out; one idea is that it is illegal to access a slot
of the object in that context after its class has been changed. When a
particular generic function invocation invokes multiple methods because of
method combination or because of call-next-method, all methods after the
one that changed the class are in "a wierd state"; this is necessary
because changing the class of an argument can change the set of available
methods, but implementations need to be free to bind that set at generic
dispatch time. In Flavors we have a more specific description of what the
user can rely on which might serve as a model."
From a message by Gregor:
"We should work out a clear description of what these restrictions are.
This restriction should probably be biased in the direction of the
implementor. Perhaps you should send out the description from flavors
as a start."
----------------------------
OK, here's the description from the Flavors documentation. The Flavors
function for CHANGE-CLASS is called CHANGE-INSTANCE-FLAVOR. The
following text describes the problems that might happen, and the last
two paragraphs tell the users what they can rely on.
Note: There are two possible problems that might occur if you use
CHANGE-INSTANCE-FLAVOR while a process (either the current process
or some other process) is executing inside of a method. The first
problem is that the method continues to execute until completion even if
it is now the "wrong" method. That is, the new flavor of the instance
might require a different method to be executed to handle the generic
function. The Flavors system cannot undo the effects of executing the
wrong method and cause the right method to be executed instead.
The second problem is due to the fact that CHANGE-INSTANCE-FLAVOR
might change the order of storage of the instance variables. A method
usually commits itself to a particular order at the time the generic
function is called. If the order is changed after the generic function
is called, the method might access the wrong memory location when trying
to access an instance variable.
When a flavor is redefined, the implicit CHANGE-INSTANCE-FLAVOR that
happens never causes accesses to the wrong instance variable or to
arbitrary locations outside the instance. But redefining a flavor
while methods are executing might leave those methods as no longer valid
for the flavor.
We recommend that you do not use CHANGE-INSTANCE-FLAVOR of SELF inside a
method. If you cannot avoid it, then make sure that the old and new
flavors have the same instance variables and inherit them from the same
components. You can do this by using mixins that do not define any
instance variables of their own, and using CHANGE-INSTANCE-FLAVOR only
to change which of these mixins are included. This prevents the
problem of accessing the wrong location for an instance variable, but it
cannot prevent a running method from continuing to execute even if it is
now the wrong method.
A more complex solution is to make sure that all instance variables
accessed after the CHANGE-INSTANCE-FLAVOR by methods that were called
before the CHANGE-INSTANCE-FLAVOR are ordered (by using the
:ORDERED-INSTANCE-VARIABLES option to DEFFLAVOR), or are inherited from
common components by both the old and new flavors. The old and new
flavors should differ only in components more specific than the flavors
providing the variables.
∂16-Dec-86 1206 RPG My remarks on Moon's comments etc.
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Sonya, normally your editing leaves the file in a state that is easily
translated into Tex, with one exception, which is very easy for you to help
us with.
PLEASE, PLEASE, PLEASE, PLEASE, PLEASE, PLEASE, PLEASE, PLEASE, PLEASE
do *NOT* use the convenient `"' key. It seems so easy to type:
"foo"
but Tex wants to see the more correct looking:
``foo''
Our having to change this is the biggest hassle (believe it or not).
Moon says:
``The introduction section needs to be written (right now it only contains
one sentence). It should explain how the functions described in this
chapter fit into the overall scheme of things, including the relation
between the basic programmer interface and the meta-objects.''
I say: let's see some of you budding authors out there produce a draft of
something, for a change.
Moon says:
``DEFGENERIC-OPTIONS:
I still think this choice of name reflects a fundamental misunderstanding,
but it won't be the first poorly chosen name in Common Lisp so I suppose
we can live with it if we have to. Having gotten that bit of steam off
my chest I can go on to substantive comments.''
I'd like to see a cogent argument for why the choice of name reflects a
fundamental misunderstanding. Especially interesting would be to see a
cogent argument for why DEFGENERIC is not misleading. After thinking about
it, I couldn't think of a more misleading name.
Moon says:
``:argument-precedence-order should be changed back to the way it was in
the previous version. These positional numbers don't add any expressive
power and do add new ways to mess up.''
Possibly. I think we thought that if people would want to SETF this part
of the generic function, it would be nicer to have a parameter-name
independent way of indicating how to change it.
Moon says,
``The :dynamic and :none allocation-types are hacks and should be
removed. In Menlo Park we spent a long time talking about the
weirdness of dynamic allocation, and my conclusion from that is
that it doesn't belong in the standard. I have no problems with
:instance and :class allocation.''
I guess I agree with this.
Other than that, I think Moon's comments are reasonable and the rest of it.
-rpg-
∂16-Dec-86 1422 Moon@STONY-BROOK.SCRC.Symbolics.COM Gabriel's remarks on Moon's comments etc.
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 16 Dec 86 14:21:51 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 24921; Tue 16-Dec-86 17:06:14 EST
Date: Tue, 16 Dec 86 17:06 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Gabriel's remarks on Moon's comments etc.
To: Common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 16 Dec 86 15:06 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861216170624.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 16 Dec 86 1206 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Moon says:
``DEFGENERIC-OPTIONS:
I still think this choice of name reflects a fundamental misunderstanding,
but it won't be the first poorly chosen name in Common Lisp so I suppose
we can live with it if we have to. Having gotten that bit of steam off
my chest I can go on to substantive comments.''
I'd like to see a cogent argument for why the choice of name reflects a
fundamental misunderstanding. Especially interesting would be to see a
cogent argument for why DEFGENERIC is not misleading. After thinking about
it, I couldn't think of a more misleading name.
I don't think it's fruitful to discuss this further, since one or both
of us is wedged.
Moon says:
``:argument-precedence-order should be changed back to the way it was in
the previous version. These positional numbers don't add any expressive
power and do add new ways to mess up.''
Possibly. I think we thought that if people would want to SETF this part
of the generic function, it would be nicer to have a parameter-name
independent way of indicating how to change it.
I don't understand what SETF has to do with the syntax of an invocation
of DEFGENERIC-OPTIONS. The syntax of the macro should be chosen for maximum
expressiveness and readability. Any internal data structure or programmatic
interface need not be constrained to the same syntax. Also I believe the thing
has both numbers and parameter-names in it, making it maximally difficult for
everyone, although I can't check this easily because my copy of the document
hasn't emerged from my recent move yet.
Maybe this was all just an accident of editing and :argument-precedence-order
wasn't supposed to have been changed when generic-function-argument-precedence-order
was changed.
∂16-Dec-86 1453 RPG Argument Precedence Order
To: common-lisp-object-system@SAIL.STANFORD.EDU
I was saying that because the value of the generic function
ARGUMENT-PRECEDENCE-ORDER was changed (so that SETF of it would make some
more sense) the same part of DEFGENERIC-OPTIONS was changed to be
consistent. If we have to go to the trouble of explaining this stupid
ARGUMENT-PRECEDENCE-ALIST anyway, we might as well let people remember
there is exactly one way to express argument precedence orders.
Sorry, from now on I won't skip obvious-to-me steps in my arguments.
If we flush the generic function ARGUMENT-PRECEDENCE-ORDER, then there is
exactly one thing with which to be compatible: MAKE-GENERIC-FUNCTION.
Moon already, correctly, points out the problems with this so-called
`programmatic' interface. We should re-think it.
By the way, my use of the word ``possibly'' should have been taken to have
the same impact as ``sure.''
-rpg-
ps. Yes, the ARGUMENT-PRECEDENCE-ALIST has parameter names and numbers in
it and is a terrible representation.
∂16-Dec-86 1509 RPG Onward ... Soldiers
To: common-lisp-object-system@SAIL.STANFORD.EDU
The next X3J13 meeting will in Palo Alto March 16, 17, 18. The
main topic of discussion will be the object system proposal. We should
have our documents ready for Mathis 3 weeks before those days so that
people will have a week or so to digest their contents.
I'm hoping that Moon will be able to make the meeting, because his comments
will be most highly valued and because his experiences will be able to
better convince people than our representations.
So, I'm confident that with Sonya at the helm currently that Moon's
comments will be rapidly folded into the draft and that the parts about method
combination will be fleshed out.
-rpg-
∂16-Dec-86 1642 Moon@STONY-BROOK.SCRC.Symbolics.COM Onward ... Soldiers
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 16 Dec 86 16:42:03 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 25146; Tue 16-Dec-86 19:40:13 EST
Date: Tue, 16 Dec 86 19:40 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Onward ... Soldiers
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 16 Dec 86 18:09 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861216194029.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 16 Dec 86 1509 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
The next X3J13 meeting will in Palo Alto March 16, 17, 18.
I'm hoping that Moon will be able to make the meeting.
Part of the reason for not going to Dallas was to free up the time
to be able to go to this one. So yes, at this point I am definitely
intending to attend.
∂16-Dec-86 1657 RPG Planning
To: common-lisp-object-system@SAIL.STANFORD.EDU
While you're all thinking about the March meeting and the heavy
workload between now and then, think about whether there ought to be
a meeting before or after for the working group.
I think we will have the functions, concepts, and rationale
chapters done (except for the Latin quotes) in time, but the
`meta-object protocol' chapter will not even be starting to be
presentable to this group. By now, the phrase ``we'll put it in
the meta-object protocol'' is beginning to mean ``trash that idea
quietly.''
Perhaps a meeting at which Danny and Gregor tell us what they think
the `meta-object protocol' really is would be appropriate.
If so, people will want to plan their travel accordingly.
-rpg-
∂17-Dec-86 0729 skeene@STONY-BROOK.SCRC.Symbolics.COM My remarks on Moon's comments etc.
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 17 Dec 86 07:28:54 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 25583; Wed 17-Dec-86 10:26:30 EST
Date: Wed, 17 Dec 86 10:26 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: My remarks on Moon's comments etc.
To: RPG@SAIL.STANFORD.EDU
cc: Common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 16 Dec 86 15:06 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861217102624.4.SKEENE@JUNCO.SCRC.Symbolics.COM>
Date: 16 Dec 86 1206 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Sonya, normally your editing leaves the file in a state that is easily
translated into Tex, with one exception, which is very easy for you to help
us with.
PLEASE, PLEASE, PLEASE, PLEASE, PLEASE, PLEASE, PLEASE, PLEASE, PLEASE
do *NOT* use the convenient `"' key. It seems so easy to type:
"foo"
but Tex wants to see the more correct looking:
``foo''
Our having to change this is the biggest hassle (believe it or not).
I'll be glad to comply with this request. YOU'RE WELCOME!
Moon says:
``The introduction section needs to be written (right now it only contains
one sentence). It should explain how the functions described in this
chapter fit into the overall scheme of things, including the relation
between the basic programmer interface and the meta-objects.''
I say: let's see some of you budding authors out there produce a draft of
something, for a change.
I wrote up an introduction section.
I've folded in the comments by Moon that were non-controversial. Right
now he's looking over the changed text, and I'll write out the revised
file soon, probably by Friday. I'll also send to the mailing list his
original message with annotations on the changes that I made to the
file, and the issues that are still open.
Thanks to Gregor, Danny, and you for responding quickly to his message.
I'm also eager to get the document in shape for the March meeting, and
it seems like we're now making good progress.
∂17-Dec-86 1234 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Comments on the revised function chapter
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 17 Dec 86 12:34:04 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 26265; Wed 17-Dec-86 15:31:24 EST
Date: Wed, 17 Dec 86 15:31 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Comments on the revised function chapter
To: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <861212-182459-1721@Xerox>
Message-ID: <861217153134.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 12 Dec 86 18:24 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
....
Just so you know, I read this message but don't have anything to add.
It looked like there were a couple of questions in the message that
Gregor needs to answer.
∂17-Dec-86 1246 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Comments on the revised function chapter
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 17 Dec 86 12:45:56 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 26265; Wed 17-Dec-86 15:31:24 EST
Date: Wed, 17 Dec 86 15:31 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Comments on the revised function chapter
To: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <861212-182459-1721@Xerox>
Message-ID: <861217153134.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 12 Dec 86 18:24 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
....
Just so you know, I read this message but don't have anything to add.
It looked like there were a couple of questions in the message that
Gregor needs to answer.
∂17-Dec-86 1510 RPG Rephrasing
To: common-lisp-object-system@SAIL.STANFORD.EDU
On re-reading my last message to this list I notice some very poor
phrasing. What I was suggesting about the meta-object protocol was that
because not many people aside from Danny and Gregor have a crisp
understanding of what it really is, that people are possibly sweeping
things under the `meta-object protocol rug,' thinking that the issue
raised by the thing being swept under the rug can be avoided.
I wanted to suggest that Danny and Gregor lead a discussion or make a
presentation so that the rest of us can come up to speed. If the
presentation were to take the form of a moderately fleshed-out proposal,
so much the better.
If there is such a discussion, it will be outside the time reserved for
X3j13, so we should select the time so that people can make appropriate
travel plans.
My apologies to those who were offended by my wording.
-rpg-
∂17-Dec-86 1524 Moon@RIVERSIDE.SCRC.Symbolics.COM Re: Comments on the revised function chapter
Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 17 Dec 86 15:24:25 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 87010; Wed 17-Dec-86 18:22:23 EST
Date: Wed, 17 Dec 86 18:22 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Comments on the revised function chapter
To: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <861209-153819-3738@Xerox>
Message-ID: <861217182238.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 9 Dec 86 15:38 PST
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Date: Thu, 4 Dec 86 00:23 EST
From: David A. Moon
These comments apply to the draft dated Nov 30, 1986 21:10.
These are my comments on your comments.
I'm going to send a separate message about each open issue where I have
something useful to say, with a different subject line on each message,
so fewer things fall through the cracks. Parts of your message that I
don't respond to are parts where I agree or that are already resolved.
This message will be just a list of issues where I don't have anything
to say right now. If someone else wants to start a real discussion they
should break the issue off into an individual message so it doesn't get
mixed up with other issues.
We need to specify make-class and put it in chapter 1.
Agreed.
Whether add-method when the method already exists signals an error or
updates the method needs to be resolved. Whether get-method signals an
error or returns nil when it can't find the method needs to be resolved.
These are related.
Some of the details of :accessor-prefix and :reader-prefix,
especially how you get it to use the slot names as the accessor
names, are still under discussion.
This hasn't converged yet.
I'm grossed out by the schizophrenia between documentation of
symbols and documentation of objects.
I agree that this is all screwed up. Do you have another proposal?
Not currently.
Whether slot-value can access defstruct slots needs to be resolved.
I don't care whether the answer is yes or no.
∂17-Dec-86 1533 Moon@RIVERSIDE.SCRC.Symbolics.COM Implementation-supplied methods for DESCRIBE and PRINT-OBJECT
Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 17 Dec 86 15:28:57 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 87013; Wed 17-Dec-86 18:27:07 EST
Date: Wed, 17 Dec 86 18:27 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Implementation-supplied methods for DESCRIBE and PRINT-OBJECT
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861217182727.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Moon: One method is enough, change "classes t and object" to "class t".
Gregor: Shouldn't there be a method on t which prints with #<FOO 213213>
syntax, and a method on object whichs uses some readable syntax like
#S(FOO A 1 B 3).
And a method on INTEGER that uses a readable syntax like 123456, and a
method on LIST, and ....?
My point is simply that it is the implementation's business whether it
uses separate methods for each class, one method that checks the type,
or some hybrid. Mandating that each implementation uses at least two
methods doesn't make sense to me.
I think the spec should just say:
Each implementation is required to provide a default method for
print-object. Implementations are free to add methods for specific
classes. Users can write methods for print-object for their own classes
if they do not wish to inherit an implementation-supplied method.
∂17-Dec-86 1542 RPG Implementation-supplied etc
To: common-lisp-object-system@SAIL.STANFORD.EDU
I agree with Moon that the spec should say:
Each implementation is required to provide a default method for
print-object. Implementations are free to add methods for specific
classes. Users can write methods for print-object for their own classes
if they do not wish to inherit an implementation-supplied method.
-rpg-
∂17-Dec-86 1631 Gregor.pa@Xerox.COM Re: Comments on the revised function chapter
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Dec 86 16:31:07 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 17 DEC 86 16:16:47 PST
Date: 17 Dec 86 16:14 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Comments on the revised function chapter
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 12 Dec 86 18:24 PST
To: Bobrow.pa@Xerox.COM
cc: Gregor.pa@Xerox.COM, Moon@STONY-BROOK.SCRC.Symbolics.COM,
Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861217-161647-5597@Xerox>
Date: 12 Dec 86 18:24 PST
From: Danny Bobrow <Bobrow.pa>
The function (get-generic-function-setf symbol) should return
the setf generic function. All those methos that require a setf
generic function should be called with that object, rather than a
list.
Right, I had forgotten that we had separately talked about this. Now
that you have reminded me, I should say that add-method etc. should
accept a generic-function or a symbol which names a generic function.
We need to decide whether get-generic-function-setf (or whatever its
called) returns a generic function object, which might be nice
sometimes. Or should it return an interned symbol which names the setf
generic function, which would make it possible to use it in macros.
Perhaps we need two functions, get-generic-function-setf and
get-generic-function-setf-name?
I suspect that this question will make Moon want to propose some sort of
function spec facility. Hopefully, we can decide this without doing
that, but say that if we had some sort of function spec facility, this
would use it in the "obvious" way.
I thought we decided (you told me) that it had to go at the
beginning to allow optionals etc. What issue remians.
Right, I should have said we need to specify, not decide. Specifically,
we need to flesh out the details and spec out that:
(defmethod-setf foo ((x boat) (y plane) ..) ((nv gasoline)) ...)
becomes *something* like:
(defmethod |foo setf| ((nv gasoline) (x boat) (y plane) ..) ...)
(defsetf foo |foo setf|)
I see no good argument for maintianing consistency in this case
(Consistency is the hobgoblin of small minds, it is said) and it
would be much more useful to have the object.
Fine, so do we make any effort at consistency here? Should all the
DEFxxx macros in this spec return an object? Or should some of them
return objects and some names? It sure will be nice to have such large
minded users that they won't ever forget what the various DEFmumble
forms return.
Of course no one ever uses the value returned from one of these, so I
don't really care that much.
SLOT-VALUE:
Can slot-value access defstruct slots?
YES since they are translated into DEFCLASSes.
Actually, on second thought, weren't we going to propose that defstruct
be removed from the language? If so, defstructs could be translated
into defclass as Danny says, and then slot-value would work. Other
defstructs could be translated into defrecord and slot value wouldn't
work.
∂17-Dec-86 1634 Moon@STONY-BROOK.SCRC.Symbolics.COM specializers list
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 17 Dec 86 16:34:04 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 26573; Wed 17-Dec-86 19:04:02 EST
Date: Wed, 17 Dec 86 19:04 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: specializers list
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861217190417.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
In the Functions chapter, specializers are used in two places:
(1) defmethod and defmethod-setf
(2) get-method and make-method
In defmethod, specializers are attached to parameter specifiers and
their format is quite well-defined.
Get-method and make-method accept a list of specializers. Get-method
says the following and make-method is compatible (but briefer):
The specializers argument is a list of the parameter specializers
for the method. It must correspond in length to the number of required
arguments of the generic function. This means that to obtain the default
method for a given generic function, a list of t's corresponding in
length to the number of required arguments of that generic function must
be given.
Two of the issues about this list of specializers that I raised on 12
November are still open:
(1) Are the list elements class objects, or the same as in defmethod
(Common Lisp type-specifiers)?
(2) A list with one element for each required argument is not extensible
to possible future specialization of keyword parameters, and may also
have problems for some of the proposals for future specialization of
optional parameters.
Issue #1 isn't directly addressed by the current spec, but it implies
that the answer is type-specifiers since it mentions a list of t's. I
mildly prefer type-specifiers, but don't see how this fits in with the
idea of unnamed classes. I expect this connects to the open issue of
make-class. At present I have no proposal on this issue.
I offer the following proposal for issue #2, to replace what the spec
says now (italics and boldface are omitted):
The specializers argument is an association list with one element for
each specialized parameter. Each element is a list, (pos type), where
pos is a non-negative integer less than the number of required
parameters of the generic function and type is [whatever we decide,
right now the same as for defmethod]. Parameter specializers of t are
omitted, so the association list is nil to refer to a default method.
Elements of the association list are ordered by pos, with the
numerically smallest pos at the beginning of the list.
Note: if the standard is extended in the future to allow optional
parameters to be specialized, pos will be allowed to be greater than or
equal to the number of required parameters.
Note: if the standard is extended in the future to allow keyword
parameters to be specialized, pos will be allowed to be a keyword symbol
and the association list will be ordered with numeric pos's preceding
symbolic pos's and symbolic pos's sorted alphabetically. CLtL appears
to allow only keyword symbols as keyword-parameter keywords, so there is
no issue of ordering symbols with identical names in different packages.
[Editorial note: I say "pos" rather than "position" to make it clear
where the italics go and to make the note about keyword parameters
less confusing.]
∂17-Dec-86 1702 Gregor.pa@Xerox.COM Re: specializers list
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 17 Dec 86 17:01:54 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 17 DEC 86 16:53:42 PST
Date: 17 Dec 86 16:53 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: specializers list
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 17 Dec 86 19:04 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861217-165342-5656@Xerox>
Date: Wed, 17 Dec 86 19:04 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Issue #1 isn't directly addressed by the current spec, but it
implies that the answer is type-specifiers since it mentions a list
of t's. I mildly prefer type-specifiers, but don't see how this
fits in with the idea of unnamed classes. I expect this connects
to the open issue of make-class. At present I have no proposal
on this issue.
Yes, this does connect with the open issue of make-class in the sense
that methods need to be specified for anonymous classes. This meants
that these type specifiers need to be class objects or (QUOTE datum).
In PCL, there is one version of add-method with takes type specifiers,
it turns around and calls another version with the class objects. I
think just the one with the class objects should be enough for the
standard.
I offer the following proposal for issue #2, to replace what
the spec says now (italics and boldface are omitted):
The specializers argument is an association list with one
element for each specialized parameter. Each element is a list,
(pos type), where ...
If we have class objects as the type specifiers then why not just use
the regular lambda list keyword sort of syntax for dealing with
optionals and keys.
so that
(defmethod foo ((x boat) (y plane)) ..)
corresponds to
(#<Class boat 123> #<Class plane 456>)
and later if we add optionals,
(defmethod bar ((c class) &optional (n symbol)) ..)
(#<Class class 789> &optional #<Class symbol 987>)
and keys:
(defmethod baz ((c class) &key (s symbol)) ..)
(#<Class class 789> &key (:s #<Class symbol 987>))
∂17-Dec-86 2033 Moon@STONY-BROOK.SCRC.Symbolics.COM Uninitialized slots
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 17 Dec 86 20:33:21 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 26793; Wed 17-Dec-86 23:31:25 EST
Date: Wed, 17 Dec 86 23:31 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Uninitialized slots
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861217233133.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Moon: The remark about slots that have not been initialized was
weakened from the previous version. You went too far; as written
this would prohibit all implementations from signalling an error
when an uninitialized slot is referenced, because legal programs
could read the slot and discard its value. Like it or not, we have
to say "is an error" here.
Gregor: We did this on purpose. I don't see why we have to say "is an error
here". Our thought was that a legal program could count on being able
to read the value of an unitialized slot, could count on the fact that
the value was a legal pointer, but could not count on what the value
was.
A standard that specifies that the contents of an uninitialized slot
is complete garbage and the ONLY thing about it that is guaranteed
is that reading it will NOT signal an error doesn't appeal to me.
In fact it seems completely backwards! If reading the slot isn't
"is an error", then the value should be guaranteed. If the value
isn't guaranteed, then any program that depends on the value is
erroneous, and when maximizing safety this error should be detected
and signalled.
The only argument in favor of your proposal that I can think of is that
it is compatible with defstruct; but this is just perpetuating a bug.
Are there other arguments I haven't thought of? If not, I strongly
recommend that referencing an uninitialized slot "signals an error."
If the stock-hardware people make a strong case for "is an error"
instead of "signals an error", I am willing to back off that far.
∂17-Dec-86 2110 RPG Uninitialized Slots
To: common-lisp-object-system@SAIL.STANFORD.EDU
Moon discusses referencing uninitialized slots.
As long as the stock hardware guys can write compilers that omit the
check with a certain safety level setting, there is no problem with
`signals' versus `is' for me.
I think there is a valid difference between phrases like `is an error'
and `is undefined.' `Is an error' implies that if something is done
that `is an error,' then in some implementation a bug will occur.
`Is undefined' implies that even if something is done that is undefined,
there might not be any implementation in which a bug will occur.
Taking the value of a slot that has not been initialized may or may
not produce a bug in some implementation; it depends on what is done
with that value. I can imagine someone writing:
(let ((unique-item (ncons ())))
(loop
(when (eq <slot-access> unique-item)
(hairy-cleanup)
(return-from ...))
...
(when (seems-like-a-good-time-to-quit)
(setf <slot-access> unique-item))
...
(when (how-about-now-p)
(setf <slot-access> unique-item))
...))
where the <slot-access> is to an uninitialized slot and where the HAIRY-CLEANUP
is a large macro. This code is ok under the undefined case, because it doesn't
matter what the value is (as long as it is an existent Lisp object) - it only
matters that it isn't this Lisp object carefully created to be different from
any others.
It is the case that if a program depends on an implementation-dependent
value for that slot the program will not be portable, but that is a
different issue.
Because the phrase `is undefined' is not used in CLtL (I think), this
distinction has not yet been used in the CL community.
I think the reasoning we used for this was that it is not an error to
access the slot, it is an error to use the value.
I have no strong opinions on this point.
-rpg-
∂17-Dec-86 2120 Moon@STONY-BROOK.SCRC.Symbolics.COM Relationship between accessors and methods
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 17 Dec 86 21:20:28 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 26816; Thu 18-Dec-86 00:18:22 EST
Date: Thu, 18 Dec 86 00:18 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Relationship between accessors and methods
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861218001833.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Moon: The relationship between accessors (methods created with
:accessor, :reader, :accessor-prefix, and :reader-prefix) and
regular methods (created with defmethod) needs to be discussed.
One issue is how they combine, e.g. (defmethod-setf foo-slot :after
((object foo)) (new-value) ...). Another is what happens if you
define a conflicting regular method, e.g. (defmethod-setf foo-slot
((object foo)) (new-value) ...) when (defclass foo () ((slot
:accessor foo-slot))) has been done.
Gregor: Right. I believe the way to make this clear is to specify that the
accessor methods are regular methods, they behave as if they were
defined by a defmethod, e.g.
(defmethod foo-slot ((foo foo)) (slot-value foo 'slot))
This isn't what we do in Flavors now, but after thinking this over for
some time I believe what you suggest is desirable. I think we would use
a different class of method-object for accessors, so it wouldn't behave
precisely the same as that defmethod. However, it would have the key
property that if you define both a regular method and an accessor, for
the same generic function and the same class, with no method qualifiers,
whichever one you define second replaces whichever one you define first.
It would also have the key property that in method combination it
behaves just like the defmethod. The difference from the defmethod
would be purely internal to the implementation, unless you examined the
type-of the method-object.
I think the Functions chapter of the documentation should be augmented
with a note, in the defclass section, explaining this quite explicitly.
(Not talking about Symbolics' or anybody else's implementation, of
course.)
∂18-Dec-86 0846 skeene@STONY-BROOK.SCRC.Symbolics.COM Changes made to the document
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Dec 86 08:45:41 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 27090; Thu 18-Dec-86 11:43:25 EST
Date: Thu, 18 Dec 86 11:43 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Changes made to the document
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861218114310.5.SKEENE@JUNCO.SCRC.Symbolics.COM>
This morning I wrote out a new version of the file functi.tex.
This message lists the things that I changed in the document according
to the comments below made by Moon. I'm also going to send two other
messages. One will list formatting changes that I did not make, and
left for Linda to take care of when she gets back. The other will list
the comments that still are open issues, and are now being discussed
further. When it seems clear that this group has reached a conclusion
on any of those issues, I'll update the file and send a message to that
effect.
Date: Thu, 4 Dec 86 00:23 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
These comments apply to the draft dated Nov 30, 1986 21:10.
The chapter title still calls it a user interface, even though what it
is actually documenting is a programmer interface.
Now called: "Functions in the Programmer Interface".
The introduction section needs to be written (right now it only contains
one sentence). It should explain how the functions described in this
chapter fit into the overall scheme of things, including the relation
between the basic programmer interface and the meta-objects.
This has been written.
The functions ARGUMENT-PRECEDENCE-ORDER, GENERIC-FUNCTION-LAMBDA-LIST,
GENERIC-FUNCTION-METHOD-COMBINATION-TYPE, and LAMBDA-LIST-SPECIALIZERS are
unnecessary and should be removed. Perhaps they are really part of the
meta-object interface, but they aren't useful by themselves.
I removed them.
ADD-METHOD, DOCUMENTATION, GENERIC-FUNCTION-LAMBDA-LIST,
GENERIC-FUNCTION-METHOD-COMBINATION-TYPE, GET-METHOD, and REMOVE-METHOD
accept an argument that can be "a generic function or a symbol that names a
generic function." I thought we agreed in October that these functions
would also accept a list (SETF symbol) as a name of a setf generic
function. Looking back through the mail, I see Gregor agreeing on 21
Oct, Bobrow agreeing on 20 Oct, and me proposing it on 17 Oct. I didn't
see any other discussion; did I miss some mail?
This change has been incorporated.
The new term "method combination identifiers" was introduced for what
we used to call "method qualifiers" without any discussion. I'm not sure
and it's an improvement and I think there ought to be some discussion.
I changed it back to method qualifier (on the phone with me Danny agreed
that this was OK).
ADD-METHOD:
Typo: 2nd para under arguments says "or with the lambda" when it means
"and with the lambda".
Fixed.
Typo: "argument specializers" should be "parameter specializers."
Fixed.
The values description is awkward. There has to be a simpler way to
phrase such a simple concept as side-effecting an object passed as
an argument and returning the same object.
Fixed.
CALL-NEXT-METHOD:
Typo: "may to be used" in 6th para under purpose.
Fixed.
Typo: first sentence in remarks is missing a comma before "affects".
Fixed.
This sentence would be clearer if it was amplified by adding a second
sentence: "Call-next-method passes the current method's original arguments
along to the next method."
Done.
This was already said under purpose, so what
we are really seeing here is the bad effect of the decision to split the
presentation of information arbitrarily among "purpose", "arguments", and
"remarks" sections. In many cases this document is unnecessarily difficult
to read because sentences that should be in the same paragraph have been
moved into separate sections. I assume this can be improved in future drafts.
Inconsistent language: we say it "is used", "may be used", is "called from",
is "done in", and is "called with". The verb "used" seems the most
appropriate and should be used consistently.
Fixed.
CHANGE-CLASS:
Typo: first sentence says "the new class" when it means "a new class".
Fixed.
This seems to imply that the second argument is not allowed to be the
name of a class. Why not?
I believe this was accidental so I changed it to allow the name of a
class.
The remarks should clarify that not all objects will allow change-class.
For example, an implementation is not required to support change-class on
any built-in object. (I don't think implementations should be prohibited
from supporting it; some built-in classes in some implementations might be
implemented using the Class system rather than being implemented in a
primitive way.)
I added that.
DEFCLASS:
Clarification: Last sentence under Purpose should make it clear that
the object can be directly an instance of the new class or can be
directly an instance of a subclass of the new class. It's important
to be explicit since people tend to get confused easily on this point.
Fixed.
Something called :initialize-only was added without discussion. This
seems to be unnecessary and should be removed, although I'll be happy
to listen to reasons why it is useful and should stay if there are
some.
I removed this.
The option :uninstantiable, formerly :instantiable, formerly :abstract is
of the same category as :required-flavors and does not belong in the
standard if the criterion is to omit merely protocol-enforcing options. It
should be removed (a good thing, since we still haven't found a decent
name for it!).
I removed it.
In the syntax for boa-arglists, supplied-p parameters should be allowed
since they can be used in initforms of later parameters. The description
of defstruct b.o.a. constructors in CLtL is too vague, but seems to imply
that supplied-p parameters are disallowed. CLtL doesn't allow &key and
&allow-other-keys in boa-arglists, but of course it should. They should
be allowed in defclass unless someone can present a good argument against
them. We have found them useful.
I added this.
Under arguments, 2nd para, I don't think the remark about built-in classes
belongs here.
Fixed.
Typo: "the a generic" under :reader.
Fixed.
The description of :allocation :instance slot-option refers to storing the
variable in the class instance. To me this sounds the same as :allocation
:class. In general, when the terms "class object" and "class instance" are
thrown around it's very difficult to keep track of which is which.
I reworded this somewhat.
Typo: "slot (storage)" under :allocation :class.
Fixed.
You forgot to say whether the :initialize-only and :type slot-options can
be given more than once.
I made :type be one of those that may be given at most once for a given
slot. There seems little point in allowing it to be given more than
once. The :initialize-only option is now removed.
Typo: "on generic function" under :accessor-prefix and :reader-prefix.
Fixed.
The vague word "processed" is used in the description of :accessor-prefix
and :reader-prefix. Use a more specific word. Do you mean evaluated or
macro-expanded? When compiling, do you mean compile time or load time?
I could go with either.
Changed to macro-expanded (according to Gregor's reply to your message).
Some of the details of :accessor-prefix and :reader-prefix, especially
how you get it to use the slot names as the accessor names, are still
under discussion and what's in the document may change.
I couldn't think of a more confusing way to describe the :metaclass option
than the way it's described here. Maybe the concept is inherently
confusing, but I think we could do better. One suggestion is always and
consistently to use the word "metaclass" to refer to a class that is the
class of a class, and reserve the word "class" entirely for the set ofb
classes that are not metaclasses.
I reworded this.
Remarks section: on redefining classes: I assume it is not permitted to
redefine a built-in class.
I added that.
The fourth bullet would be
less confusing if it were rephrased in the singular.
Done.
The last sentence under remarks implies that the :allocation slot-option
can only be used in one slot-description in a defclass. This is not
what you meant to say! I would break this into two sentences: "No other
class option may appear more than once in a single defclass form. No
other slot-option may appear more than once in a single slot-description."
Done.
DEFGENERIC-OPTIONS:
I still think this choice of name reflects a fundamental misunderstanding,
but it won't be the first poorly chosen name in Common Lisp so I suppose
we can live with it if we have to. Having gotten that bit of steam off
my chest I can go on to substantive comments.
:argument-precedence-order should be changed back to the way it was in
the previous version. These positional numbers don't add any expressive
power and do add new ways to mess up.
Done.
declare option: the optimize declaration seems to have gotten lost in
editing. I would expect this to be the most useful declaration in most
implementations, except for very simple ones that won't do anything with
the advice because they have only one form of generic dispatching.
I put back optimize.
DEFGENERIC-OPTIONS-SETF:
Typo: The second sentence under purpose says "generic-function-name" but
should say "name" to be consistent with the rest of the page.
Done.
The last sentence under arguments, about the setf-lambda-list, isn't really
true since no variables are getting bound here. The variable name is
really just documentation. I'd say this text was accidentally copied from
defmethod-setf, except that it doesn't appear there. Move it to there.
Done.
DEFMETHOD:
What happens if "name" currently names a non-generic function? For consistency
with defgeneric-options, defmethod should signal an error.
Done.
In the second para under purpose, the list of attributes for creating a
generic function is somewhat garbled. G.f.'s don't have parameter specializers.
Lambda-list and method-combination need to be mentioned.
Typo: under arguments, "arguments, have t" should be "arguments have t".
Done.
The value returned by defmethod was changed from a method object, in the
previous version, to a rather hokey list. This was not discussed over the
mail unless I missed some mail. I think this should be changed back.
I changed it back to return the method object.
DEFMETHOD-SETF
Typo: The phrase "stuff?]" mysteriously appears under arguments.
Fixed.
I still don't like returning a hokey list instead of an object as the value.
I changed it back to return the method object.
DESCRIBE:
One method is enough, change "classes t and object" to "class t".
Done. Also, added the text you and RPG suggested here.
DOCUMENTATION:
In the first sentence under purpose, why does it say "class object"
but not "method object"? This is very confusing.
I bet this was left out accidentally, so I added "method object".
I'm grossed out by the schizophrenia between documentation of symbols
and documentation of objects. Saying that if the first argument is
not a symbol, the second argument must be unsupplied would help a
little.
I did that.
GET-METHOD:
What happens if you ask for a default method when the symbol given as
the first argument names a non-generic function? Does it signal an error
or return a method object representing that function? The former would
seem to be more consistent with some other functions in this version of
the spec.
I added that an error is signalled, according to Gregor's reply.
MAKE-INSTANCE:
Typo: "instance of class" should be "instance of a class"
Done.
Typo: :instantiable option was renamed (but I say it should be removed).
I removed it.
PRINT-OBJECT
The arguments are an object and a stream; same as PRIN1 except that
the stream is not optional and cannot be T or NIL.
Done.
The value is the first argument (the object).
Done.
One method is enough, change "classes t and object" to "class t".
Done. Also, added the text you and RPG suggested here.
REMOVE-METHOD:
Typo: A sentence about argument list congruency was inadvertently
copied from add-method.
Fixed.
Value should be described the same way as add-method (after add-method's
value description is rewritten in English).
Done.
SLOT-VALUE:
What if no slot with that name exists? Does it signal an error, "is" an
error, or return something?
I added signals an error.
WITH-SLOTS:
In the last sentence under purpose, "unless the value of the :use-accessors
argument is nil" should be "unless the :use-accessors argument is nil",
since this argument is not evaluated. In general it should be clarified
that none of the options in this special form are evaluated.
The first sentence under arguments doesn't make sense since everything
is an instance of a class.
It now says:
The instance-form should evaluate to an object that has slots,
such as an instance of a user-defined class. Instances of built-in
classes do not have slots.
Second para under arguments: "instance" in italics should be
"instance-form".
Fixed.
First bullet under arguments: Typo: "method form" should be
"method body".
Fixed.
Second bullet under arguments: hyphens at the end of the prefix
are used inconsistently.
In the past we had it that the prefix string was prepended to the name
of the slot, and if there was a hyphen it had to be put in by the user.
The examples use this too. I made this section consistently use that
idea.
The vague word "processed" appears again
(see defclass).
I changed it to "macro-expanded".
Under examples, comments contrasting the two move methods that were
lost in earlier editing are still missing.
Fixed.
The let should be removed
from the make-horizontal method since instance-forms can be any form,
and the indentation of this method should be corrected.
Done.
Some remarks that were present in the previous version seem to have
been lost in editing, unless the printer I used loses text from
the last page (nothing would surprise me!). The remarks were that
setq is allowed as well as setf, that it signals an error if the
class is not specified or implied, and that it signals an error if
pseudo-variable names clash.
I put those remarks back in again.
∂18-Dec-86 0848 skeene@STONY-BROOK.SCRC.Symbolics.COM List of open issues
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Dec 86 08:48:33 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 27099; Thu 18-Dec-86 11:46:44 EST
Date: Thu, 18 Dec 86 11:46 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: List of open issues
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861218114632.6.SKEENE@JUNCO.SCRC.Symbolics.COM>
This message lists the issues that need further discussion. I have not
make any changes to the document regarding these issues.
Date: Thu, 4 Dec 86 00:23 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
These comments apply to the draft dated Nov 30, 1986 21:10.
Why do we have make-generic-function, make-instance, and make-method, but
no make-class?
Comments on specific functions:
ADD-METHOD
Add-method was changed to signal an error if an equivalent method already
exists, instead of replacing it. There doesn't appear to be a way any more
to replace a method. I also don't see a way to update the definition of a
method while keeping the same method object. In the absence of such
facilities it's not very useful to document add-method.
CHANGE-CLASS
In Menlo Park we discussed restrictions on when change-class could be
called. They belong here. My notes from that meeting indicate that we
agreed on the general idea of the restrictions, but couldn't come up with a
good way of explaining it in the meeting, and said we should work on that
over the mail. The general idea was that if execution is inside of a
context in which the class of an object is declared lexically, e.g. inside
a method or inside a with-slots, then changing the class of that object
leaves the activation record of that context in "a wierd state", because of
early binding by compilers. The exact details of what "a wierd state"
means weren't worked out; one idea is that it is illegal to access a slot
of the object in that context after its class has been changed. When a
particular generic function invocation invokes multiple methods because of
method combination or because of call-next-method, all methods after the
one that changed the class are in "a wierd state"; this is necessary
because changing the class of an argument can change the set of available
methods, but implementations need to be free to bind that set at generic
dispatch time. In Flavors we have a more specific description of what the
user can rely on which might serve as a model.
DEFCLASS
We have not agreed on the name :initform yet; this needs discussion.
The :dynamic and :none allocation-types are hacks and should be removed.
In Menlo Park we spent a long time talking about the weirdness of
dynamic allocation, and my conclusion from that is that it doesn't
belong in the standard. I have no problems with :instance and :class
allocation.
Why is the temporary copy of class object
created when it is redefined given a name at all? Since when are we
redefining the Common Lisp EQUAL function?
The remark about slots that have not been initialized was weakened from the
previous version. You went too far; as written this would prohibit all
implementations from signalling an error when an uninitialized slot is
referenced, because legal programs could read the slot and discard its
value. Like it or not, we have to say "is an error" here.
The relationship between accessors (methods created with :accessor, :reader,
:accessor-prefix, and :reader-prefix) and regular methods (created with
defmethod) needs to be discussed. One issue is how they combine, e.g.
(defmethod-setf foo-slot :after ((object foo)) (new-value) ...).
Another is what happens if you define a conflicting regular method, e.g.
(defmethod-setf foo-slot ((object foo)) (new-value) ...) when
(defclass foo () ((slot :accessor foo-slot))) has been done.
DEFGENERIC-OPTIONS:
DECLARE OPTION
The
reference to the FTYPE declaration doesn't make any sense; probably it is a
typo for TYPE declarations of parameters. If FTYPE was really intended,
I'm confused and some explanation and an example should be added.
DOCUMENTATION:
Why is documentation said to be generic? Are users supposed to write
methods for it?
I'm grossed out by the schizophrenia between documentation of symbols
and documentation of objects. Saying that if the first argument is
not a symbol, the second argument must be unsupplied would help a
little. It's still going to add new inconsistencies to Common Lisp;
consider that (DOCUMENTATION (SYMBOL-FUNCTION foo)) will work if
foo is the name of a generic function, but not if foo is the name of
a regular function. I would prefer for DOCUMENTATION to be left the
way it is, as an operation on names rather than an operation on objects.
If I do (SETF (SYMBOL-FUNCTION 'BAR) (SYMBOL-FUNCTION 'FOO)), do
occurrences of the string FOO in examples in the documentation
automatically get changed to BAR? I assume the reason someone is
proposing to change documentation to be object-oriented is because
Common Lisp is defective and doesn't have any names for methods, because
only symbols can be used as names. We could fix that.
GET-METHOD
I've argued against this form of the specializers list before, so I won't
bore you by repeating my claims that doing it this way won't work well.
Please reread the mail.
MAKE-GENERIC-FUNCTION:
Under remarks it says this is the programmatic interface to defgeneric-options,
but in fact this function does not do the same thing. Defgeneric-options
can update an existing generic function.
I think some of the keyword arguments must be required. Which ones?
MAKE-METHOD:
I would think a method object would want to know what generic-function it
was for; another argument should be added. It at least wants to know this
for purpose of printing out.
What are the requirements on the function: arguments, results, and environment
for call-next-method? I prefer that only functions that have been blessed
by the generic-function meta-object before being compiled be allowed. I
suppose we could allow any function here with naive arguments, but then
we just have to have MAKE-METHOD-REAL, which is the one DEFMETHOD really
uses.
SLOT-VALUE:
Do built-in objects have slots?
Can slot-value access defstruct slots?
WITH-SLOTS:
What happens if the restriction discussed is
violated? Signal an error?
There is a serious bug in WITH-SLOTS. Unlike DEFCLASS, which is
always used at top level and therefore is macroexpanded with a
predictable value of *PACKAGE*, interpreters that do not fully
macroexpand at the time DEFUN is evaluated, which CLtL permits,
will macroexpand WITH-SLOTS in an unpredictable dynamic environment
and therefore with an unpredictable value of *PACKAGE*. I have
two suggestions for fixing this, both fairly distasteful. One
is to document the bug and say that WITH-SLOTS with :PREFIX should
only be used in compiled code. The other is to eliminate the
:PREFIX option and say that cases that are so complicated should
just call the accessors explicitly.
∂18-Dec-86 0849 skeene@STONY-BROOK.SCRC.Symbolics.COM formatting changes needed
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Dec 86 08:49:48 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 27101; Thu 18-Dec-86 11:47:55 EST
Date: Thu, 18 Dec 86 11:47 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: formatting changes needed
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861218114742.7.SKEENE@JUNCO.SCRC.Symbolics.COM>
Date: Thu, 4 Dec 86 00:23 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
These comments apply to the draft dated Nov 30, 1986 21:10.
I don't like the presentation of options with a bullet followed by a
sentence containing somewhere the option name. People want the option
name to be first, and exdented to the left margin, so they can easily
find the description of an option. Also, the textual description of
options often refers to the arguments of an option with italicized words,
but these arguments are not defined locally; you have to go back to the
syntax section to find them. This is particularly bad in defclass, because
its writeup is so big. The previous version, which repeated the syntax
pattern of an option as a header on its textual description, was better.
I agree with you, but I'm going to leave it up to Linda since it's a
formatting issue. I hope she does put back the syntax pattern of each
option.
DEFCLASS:
slot-name is not defined in the syntax figure.
I left this for Linda.
In the last line under syntax, I would prefer (QUOTE datum) rather than 'datum.
Being explicit is always a good idea.
Left for Linda.
DEFMETHOD-SETF:
Typo: an asterisk in the syntax for specialized-setf-lambda-list
should be a right parenthesis.
Left for Linda.
∂18-Dec-86 1229 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Comments on the revised function chapter
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Dec 86 12:28:46 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 27383; Thu 18-Dec-86 15:26:51 EST
Date: Thu, 18 Dec 86 15:26 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Comments on the revised function chapter
To: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <861217-161647-5597@Xerox>
Message-ID: <861218152658.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 17 Dec 86 16:14 PST
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Date: 12 Dec 86 18:24 PST
From: Danny Bobrow <Bobrow.pa>
The function (get-generic-function-setf symbol) should return
the setf generic function. All those methos that require a setf
generic function should be called with that object, rather than a
list.
Right, I had forgotten that we had separately talked about this. Now
that you have reminded me, I should say that add-method etc. should
accept a generic-function or a symbol which names a generic function.
This is in the document already.
We need to decide whether get-generic-function-setf (or whatever its
called) returns a generic function object, which might be nice
sometimes. Or should it return an interned symbol which names the setf
generic function, which would make it possible to use it in macros.
Perhaps we need two functions, get-generic-function-setf and
get-generic-function-setf-name?
I don't understand why anyone needs to write macros that know what
(setf (foo ...) ...) expands into when (setf foo) is a generic function.
That is purely setf's dirty laundry.
I suspect that this question will make Moon want to propose some sort of
function spec facility. Hopefully, we can decide this without doing
that, but say that if we had some sort of function spec facility, this
would use it in the "obvious" way.
Having proposed function specs five times in as many years and gotten nothing
but shit, I'm not interested in spending any more effort on this. Fortunately,
it doesn't appear to be essential to the success of the object-oriented
programming standard. One thing I firmly believe now is that anything in the
standard that commits either to having function specs or to not having
function specs is at an inappropriately low level of abstraction.
...............
I thought we decided (you told me) that it had to go at the
beginning to allow optionals etc. What issue remians.
Right, I should have said we need to specify, not decide. Specifically,
we need to flesh out the details and spec out that:
(defmethod-setf foo ((x boat) (y plane) ..) ((nv gasoline)) ...)
becomes *something* like:
(defmethod |foo setf| ((nv gasoline) (x boat) (y plane) ..) ...)
(defsetf foo |foo setf|)
I don't understand why any of this has to be specified. This is purely
implementation detail; all that's necessary for the language specification
is to say that the correct information is communicated to setf. Even at
the meta-object level it would be better to abstract this out of sight
e.g. by doing it with implementation-supplied methods on essential-method.
By the way, the code you've given above doesn't work. If you're going to
change the order of arguments you have to use the complex form of defsetf.
...............
[about the value returned by defmethod]
I see no good argument for maintianing consistency in this case
(Consistency is the hobgoblin of small minds, it is said) and it
would be much more useful to have the object.
Fine, so do we make any effort at consistency here? Should all the
DEFxxx macros in this spec return an object? Or should some of them
return objects and some names? It sure will be nice to have such large
minded users that they won't ever forget what the various DEFmumble
forms return.
Of course no one ever uses the value returned from one of these, so I
don't really care that much.
Hey, if it's an "object-oriented system", they should all return the object.
Is there any harm in returning the object? If not, let's go with that
consistently. (Sorry, I'm small-minded.)
...............
SLOT-VALUE:
Can slot-value access defstruct slots?
YES since they are translated into DEFCLASSes.
Actually, on second thought, weren't we going to propose that defstruct
be removed from the language? If so, defstructs could be translated
into defclass as Danny says, and then slot-value would work. Other
defstructs could be translated into defrecord and slot value wouldn't
work.
I don't care what we say about slot-value versus defstruct as long as we
don't leave the users guessing. I suggest that the simplest thing is to
remove all connections between object-oriented programming and defstruct.
∂18-Dec-86 1345 Gregor.pa@Xerox.COM Re: Implementation-supplied etc
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Dec 86 13:45:34 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 18 DEC 86 13:33:30 PST
Date: 18 Dec 86 13:33 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Implementation-supplied etc
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 17 Dec 86
15:42 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861218-133330-6493@Xerox>
I was confused about default methods for print-object and describe. I
now understand that the spec should say (as Moon pointed out):
Each implementation is required to provide a default method for
print-object. Implementations are free to add methods for specific
classes. Users can write methods for print-object for their own
classes
if they do not wish to inherit an implementation-supplied method.
∂19-Dec-86 2055 Moon@STONY-BROOK.SCRC.Symbolics.COM DECLARE option to DEFGENERIC(-OPTIONS)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 19 Dec 86 20:55:10 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 28623; Fri 19-Dec-86 23:54:03 EST
Date: Fri, 19 Dec 86 23:53 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: DECLARE option to DEFGENERIC(-OPTIONS)
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861219235343.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
What's in the Functions chapter right now for the DECLARE option to
DEFGENERIC(-OPTIONS) doesn't make complete sense. I'm confused and I may
not be alone. How about if I start by explaining how we use the DECLARE
option in DEFGENERIC in Flavors.
In Symbolics' system there are two kinds of declarations that can appear at
the head of a function. One kind controls how the body of the function is
compiled or interpreted. The second kind makes proclamations about the
function that are useful to callers. The first kind doesn't make sense in
a generic function, since it doesn't have a body, but the second kind makes
sense for both ordinary and generic functions.
Typical examples of the second kind, from our system, are (1) specifying
the number of values returned and giving names to them; (2) specifying that
the function has no side-effects. There are several others. All of these
declarations say something about the contract of the function, which can be
used for documentation, for compiler warnings, and/or can be built into
callers by a compiler authorized to optimize. An important point:
declaring that the function has no side-effects is different from the
compiler deducing this by analyzing the code. The latter applies only to
the current definition of the function, but the former is a contract, a
promise that if the function is redefined it still will have no
side-effects.
The reasons this is done with declarations rather than proclamations are
three: It is nicer syntactically to have all the information about a
function in one place, rather than in several top-level forms, and to avoid
repeating the name of the function in each proclamation. It is much more
convenient syntactically, when using macros that define functions, to
express the proclamations about the function in the same place as the body.
Most important, doing it this way instead of using PROCLAIM attaches the
information to the function object, rather than to the name of the function,
which can be important in certain cases when we're being object-oriented
rather than name-oriented.
The CLtL book only explicitly admits the existence of the first kind of
declaration, but I thought (perhaps mistakenly) that some compilers
(not ours) used the TYPE declaration (including its abbreviated forms
from Table 4-1) as a declaration of the second kind. Specifically,
I thought
(defun foo (x)
(declare (type single-float x))
...)
implied
(proclaim '(ftype (function (single-float) t) foo)).
If this is true, obviously it makes just as much sense for a generic function
as for a regular function. Note that this is different from what the
CLOS Functions chapter currently says, where it speaks of an ftype
declaration, which is different from an ftype proclamation and different
from a type declaration.
Because of this, and for other reasons, I assume that Symbolics' is not the
only implementation with declarations of the second kind, and therefore
they should be allowed in DEFGENERIC-OPTIONS. This is part of my model
(which Dick doesn't like) that DEFGENERIC is just like DEFUN except it
doesn't have a body.
In addition to all this, we also allow the OPTIMIZE declaration in
DEFGENERIC. This is a declaration of the first kind, but we interpret
it as referring to the discrimination implementation rather than to
the nonexistent body. Using the OPTIMIZE declaration seemed to make more
sense than inventing a whole new language for describing optimization
preferences, which is what we were going to do originally. Gregor said
"I think the optimize declarations would be better handled by using a
different class of generic function", but I disagree. The important
difference is that the declaration expresses the user's preference, while
the generic function class involves the user in designing or at least
choosing the implementation. The latter is much lower-level. As Gregor
said, the declaration is more portable. He ended "I would be willing to put
optimize back."
There are also a couple of typos and unfelicitous phrasings in the current
text, but they will probably go away naturally when the results of the
discussion I'm trying to start here are incorporated, so I'll skip them for
now.
∂19-Dec-86 2106 Moon@STONY-BROOK.SCRC.Symbolics.COM with-slots & interning of constructed symbols
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 19 Dec 86 21:06:36 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 28630; Sat 20-Dec-86 00:05:27 EST
Date: Sat, 20 Dec 86 00:05 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: with-slots & interning of constructed symbols
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861220000509.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Moon:
There is a serious bug in WITH-SLOTS. Unlike DEFCLASS, which
is always used at top level and therefore is macroexpanded with a
predictable value of *PACKAGE*, interpreters that do not fully
macroexpand at the time DEFUN is evaluated, which CLtL permits,
will macroexpand WITH-SLOTS in an unpredictable dynamic environment
and therefore with an unpredictable value of *PACKAGE*.
I have two suggestions for fixing this, both fairly distasteful. One is
(1) to document the bug and say that WITH-SLOTS with :PREFIX should only be
used in compiled code. The other is
(2) to eliminate the :PREFIX option and say that cases that are so
complicated should just call the accessors explicitly.
Gregor:
I have a third solution.
(3) When there is a :prefix, intern the resulting
symbol in the package of the prefix. Theoretically, this has exactly
the same problems as the proposal to make defclass intern accessors in
the package of the slot-name. But I believe this will be MUCH less
likely to happen since prefixes usually end in -, and people don't
usually export symbols which end in -. This is what PCL does now.
In fact, we might want to think about doing this to defclass as well.
We certainly should keep DEFCLASS and WITH-SLOTS consistent.
We could easily detect that the prefix is an exported symbol and complain,
but this wouldn't detect symbols that have been imported, which can also
have a home-package different from the "current" package and therefore
cause unexpected behavior.
I still find all three suggestions distasteful. On reflection, (1) is
unacceptable. I could accept either (2) or (3). I think I can make a
good case for (2), so if anyone has a counterargument that the :PREFIX
option is important, I'd really like to hear it, and it will probably
make me switch my vote to (3).
Let's hear some other opinions.
∂20-Dec-86 1243 RPG DECLARE option to DEFGENERIC(-OPTIONS)
To: Common-Lisp-Object-system@SAIL.STANFORD.EDU
Moon says of declarations:
``The first kind doesn't make sense in a generic function, since it
doesn't have a body...''
Is this true? Suppose the second argument to a generic function (and,
therefore, to each method) is always to be a single-float. Then there is
no need to repeat the declaration in every DEFMETHOD when it could be
placed in the DEFGENERIC-OPTIONS (the generic function). A generic
function has no body right there, but it has a body, which is precisely
the union of the distributed DEFMETHOD bodies. I think this sort of
declaration can make sense in a generic function.
He voices an argument, which could be applied to this very case, when
he says:
``It is nicer syntactically to have all the information about a function
in one place, rather than in several top-level forms...''
Moon says:
``I thought
(defun foo (x)
(declare (type single-float x))
...)
implied
(proclaim '(ftype (function (single-float) t) foo)).''
The first does imply the second, but the second implies nothing of use,
therefore it is rare for a Common Lisp to perform the PROCLAIMation when
it sees the first DECLAREation. The proclamation means:
FOO takes one argument, and if that argument happens to a a single-float,
then you can be assured that the single result is of type T.
Well, the compiler can already figure out the single-valuedness, so there
is no additional information from the proclamation. (Yes, this does imply
that the current Common Lisp declaration system is less worthwhile than
it could be.)
Moon writes:
``This is part of my model (which Dick doesn't like) that DEFGENERIC is
just like DEFUN except it doesn't have a body.''
What I like about generic functions is the dichotomy of generic functions
and methods - they are not the same. I fear that Moon's model would tend
to confuse the two in user's minds.
The main thing I don't like about Moon's model is the choice of name,
DEFGENERIC, which implies that a DEFGENERIC must be evaluated before any
DEFMETHODs. With a name like DEFGENERIC-OPTIONS, no user is going to even
start to think he must put one at the start of a file.
But, one or both of us is wedged, so we shouldn't re-argue this point.
I think Moon's OPTIMIZE analysis is right.
-rpg-
∂20-Dec-86 2333 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Comments on the revised function chapter
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 20 Dec 86 23:32:55 PST
Received: from ti-csl by csnet-relay.csnet id bq07398; 21 Dec 86 1:51 EST
Received: from Jenner (jenner.ARPA) by tilde id AA14297; Fri, 19 Dec 86 11:48:02 cst
To: Common-Lisp-Object-System@SU-AI.ARPA
Subject: Comments on the revised function chapter
Date: 19-Dec-86 11:47:32
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2744387249@Jenner>
Defgeneric-options:
It bothers me that the class of a method is determined at the generic function level.
I think that we are forcing too many things in the generic function. See my mail on
method combination selection.
Anyway, if the class of methods has to be constant on a generic function, then it really means
that the generic function knows about the method class. This means that the method class can be
defined as a mixin of the generic function class. Then we could get rid of the :METHOD-CLASS keyword.
make-method:
There is something missing here. How does it know about the method-class? How would the caller
know about choosing the right method-class? Since it depends on the generic-function, the caller
has to know about the generic function he is making the method for. I support David's comment:
"I would think a method object would want to know what generic-function it
was for; another argument should be added."
It seems to be the cleanest solution to this problem.
From David:
"I assume the reason someone is
proposing to change documentation to be object-oriented is because
Common Lisp is defective and doesn't have any names for methods, because
only symbols can be used as names. We could fix that."
DOCUMENTATION is not the only function having to change because methods don't have names.
TRACE will not work either. Giving names to methods (other than phony symbol names) is a
good idea. Then DEFMETHOD could return a name as other DEF forms do.
I am in favor of changing ARGUMENT-PRECEDENCE-ORDER back to an ordered list.
Patrick.
∂21-Dec-86 1657 masinter.PA@Xerox.COM with-slots
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Dec 86 16:57:05 PST
Received: from Chardonnay.ms by ArpaGateway.ms ; 21 DEC 86 16:52:45 PST
From: masinter.PA@Xerox.COM
Date: 21 Dec 86 16:50:44 PST
Subject: with-slots
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <861221-165245-8480@Xerox>
I'm having trouble saying this, so bear with me.
One of the problems with with-slots is that the local semantics of
reference depend upon distant information. Generally, it is OK for the
semantics of behavior to depend on distant information, but reference is
generally local. For example, in
(defmethod foo ((a frob) buzzer c) (with-slots a .... buzzer ...))
the reference to buzzer could either be the argument or the buzzer slot
of a, depending on the distant information of whether frobs have
buzzers. No other language construct in Common Lisp has as serious a
difficulty; although similar situations can arise with fluid vs local
references in some situations.
The second problem with with-slots is the difficulty of implementing it
correctly in the face of macros which presume (unfortunately, but
legitimately in Common Lisp) that symbols refer to variables and do not
invoke computations.
The third problem with with-slots is a design problem which we might be
able to solve, but where none of the solutions are quite satisfactory,
namely, in which package(s) should the symbols created with a :prefix
argument be interned.
Consider the possibility of removing with-slots from the proposal to be
submitted in March. It is a syntactic extension which can be added later
to any implementation. (To contrast it with, say, the meta-object
protocol, which cannot be added after the fact.)
∂22-Dec-86 1211 Bobrow.pa@Xerox.COM Re: DECLARE option to DEFGENERIC(-OPTIONS)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Dec 86 12:10:55 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 22 DEC 86 12:02:33 PST
Date: 22 Dec 86 12:02 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: DECLARE option to DEFGENERIC(-OPTIONS)
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 20 Dec 86
12:43 PST
To: RPG@SAIL.STANFORD.EDU
cc: Common-Lisp-Object-system@SAIL.STANFORD.EDU
Message-ID: <861222-120233-8937@Xerox>
Gabriel writes:
Well, the compiler can already figure out the
single-valuedness, so there is no additional information from the
proclamation. (Yes, this does imply that the current Common Lisp
declaration system is less worthwhile than it could be.)
But this information in the generic function makes this be a contract
available to the user before any method is defined (so the compiler
cannot yet do any analysis). This is to agree with Moon's example:
An important point: declaring that the function has no
side-effects is different from the compiler deducing this by
analyzing the code. The latter applies only to the current
definition of the function, but the former is a contract, a promise
that if the function is redefined it still will have no
side-effects.
I think the discussion on p158-9 of CLtL about ftype declarations
implies that these are of BOTH Moon's first kind (for the implementation
of the function) and the second kind (for the caller -- e.g. to know
they can count on typed results). FTYPE declarations in
DEFGENERIC-OPTIONS requires that defining a method that conflicts with
the implied class structure for a discriminated argument should signal
an error.
I agree that we should also allow the OPTIMIZE declaration in
DEFGENERIC-OPTIONS for the reasons given.
danny
∂22-Dec-86 1211 Bobrow.pa@Xerox.COM Re: with-slots & interning of constructed symbols
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Dec 86 12:11:04 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 22 DEC 86 12:06:58 PST
Date: 22 Dec 86 12:06 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: with-slots & interning of constructed symbols
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sat, 20 Dec 86 00:05 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861222-120658-8939@Xerox>
Moon says:
I still find all three suggestions distasteful. On reflection, (1) is
unacceptable. I could accept either (2) or (3)
(2) to eliminate the :PREFIX option and say that cases that are so
complicated should just call the accessors explicitly.
(3) When there is a :prefix, intern the resulting
symbol in the package of the prefix.
Moon prefers (has an argument for)(2). My intuition agrees with his,
but then I wonder about the prefix argument for DEFCLASS. Do you
believe interning of accessor names should use the pacakage of the
prefix there?
danny
∂22-Dec-86 1218 Moon@STONY-BROOK.SCRC.Symbolics.COM DECLARE option to DEFGENERIC(-OPTIONS)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 22 Dec 86 12:18:40 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 29588; Mon 22-Dec-86 15:17:26 EST
Date: Mon, 22 Dec 86 15:17 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: DECLARE option to DEFGENERIC(-OPTIONS)
To: Common-Lisp-Object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 20 Dec 86 15:43 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861222151707.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
[This is not an answer to the main part of your message,
but just a side-issue.]
Date: 20 Dec 86 1243 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Moon says:
``I thought
(defun foo (x)
(declare (type single-float x))
...)
implied
(proclaim '(ftype (function (single-float) t) foo)).''
The first does imply the second, but the second implies nothing of use,
therefore it is rare for a Common Lisp to perform the PROCLAIMation when
it sees the first DECLAREation. The proclamation means:
FOO takes one argument, and if that argument happens to a a single-float,
then you can be assured that the single result is of type T.
Well, the compiler can already figure out the single-valuedness, so there
is no additional information from the proclamation. (Yes, this does imply
that the current Common Lisp declaration system is less worthwhile than
it could be.)
This answer leaves me even more confused about declarations than before.
I would have expected the proclamation to mean that foo takes one argument
and that argument is -required- to be a single-float.
I can't find anything in CLtL about the semantics of the ftype
declaration at all, only about its syntax, but perhaps I'm looking in
the wrong chapter. Where in CLtL does it say what you said?
∂22-Dec-86 1310 RPG DECLARE option to DEFGENERIC(-OPTIONS)
To: common-lisp-object-system@SAIL.STANFORD.EDU
Many people don't have a correct understanding of the weak nature of FTYPE
specifiers. I've felt that there should be a stronger general form that
states that the arguments must be at most as specified.
Moon poses the question:
``Where in CLtL does it say what you said?''
The explanation starts on page 47, at the bottom. The key to understanding the
text is understanding the phrase ``accepts arguments at least of the types
specified.'' Here, ``at least'' means that more general types can be accepted.
On page 48 is the killer example:
``CONS is of type (FUNCTION (FLOAT STRING) LIST), because it can certainly
accept a floating-point number and a string (among other things)....''
And we certainly don't think that CONS's arguments are -required- to
be a FLOAT and a STRING.
-rpg-
∂22-Dec-86 1348 Bobrow.pa@Xerox.COM Re: DECLARE option to DEFGENERIC(-OPTIONS)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Dec 86 13:48:04 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 22 DEC 86 13:48:00 PST
Date: 22 Dec 86 13:47 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: DECLARE option to DEFGENERIC(-OPTIONS)
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 22 Dec 86
13:10 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861222-134800-9078@Xerox>
Many people don't have a correct understanding of the weak
nature of FTYPE specifiers. I've felt that there should be a
stronger general form that states that the arguments must be at
most as specified.
I agree. I certainly interpeted the ftype form as meaning "at most"
rather than "at least" for outputs. What is the story with outputs. It
is an "at most" specification, correct???
danny
∂22-Dec-86 1358 Bobrow.pa@Xerox.COM Re: Comments on the revised function chapter
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Dec 86 13:58:41 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 22 DEC 86 13:58:44 PST
Date: 22 Dec 86 13:57 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Comments on the revised function chapter
In-reply-to: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET's message of 19 Dec
86 11:47:32
To: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
cc: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861222-135844-9094@Xerox>
It bothers me that the class of a method is determined at the
generic function level. I think that we are forcing too many things
in the generic function. See my mail on method combination
selection. Anyway, if the class of methods has to be constant on a
generic function, then it really means that the generic function
knows about the method class. This means that the method class can
be defined as a mixin of the generic function class. Then we could
get rid of the :METHOD-CLASS keyword.
The class of methods does not have to be constant on a generic function.
The :METHOD-CLASS option only specifies the class to be used for methods
constructed using DEFMETHOD. Using ADD-METHOD, any compatible method
type can be added to a generic function.
make-method: There is something missing here. How does it know
about the method-class?
This is used only to make methods of type METHOD. Otherwise we can
create other classes of methods using
(make-instance <other-method-class>).
DOCUMENTATION is not the only function having to change because
methods don't have names. TRACE will not work either. Giving names
to methods (other than phony symbol names) is a good idea. Then
DEFMETHOD could return a name as other DEF forms do.
Having a name, and printing so the user can understand are two different
operations. Methods should certainly know how to print themselves for
readability. And TRACE can be made a generic function that takes a
method object as an argument. The method object can be located from the
generic function using (GET-METHOD <g-f> <specifiers>). This allows
methods on unnamed generic-functions to be traced as well.
I am in favor of changing ARGUMENT-PRECEDENCE-ORDER back to an
ordered list.
After thinking again, I too favor this unchange.
danny
∂22-Dec-86 1745 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: with-slots & interning of constructed symbols
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 22 Dec 86 17:44:53 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 29852; Mon 22-Dec-86 20:43:52 EST
Date: Mon, 22 Dec 86 20:43 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: with-slots & interning of constructed symbols
To: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <861222-120658-8939@Xerox>
Message-ID: <861222204333.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 22 Dec 86 12:06 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Moon says:
I still find all three suggestions distasteful. On reflection, (1) is
unacceptable. I could accept either (2) or (3)
(2) to eliminate the :PREFIX option and say that cases that are so
complicated should just call the accessors explicitly.
(3) When there is a :prefix, intern the resulting
symbol in the package of the prefix.
Moon prefers (has an argument for)(2). My intuition agrees with his,
but then I wonder about the prefix argument for DEFCLASS. Do you
believe interning of accessor names should use the pacakage of the
prefix there?
I think either way will work for DEFCLASS, since it is a top-level form.
For DEFCLASS, I would be guided by consistency with WITH-SLOTS:
If we select alternative (2), I would leave DEFCLASS the way it is.
If we select alternative (3), I would change DEFCLASS to be consistent
with WITH-SLOTS.
If we take alternative (4) [Masinter's proposal to get rid of WITH-SLOTS],
I would leave DEFCLASS the way it is.
I think I prefer (2) the best and (4) the least. None of the three stands
out, to me, as obviously right.
∂22-Dec-86 1931 Moon@STONY-BROOK.SCRC.Symbolics.COM DECLARE option to DEFGENERIC(-OPTIONS)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 22 Dec 86 19:31:13 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 29891; Mon 22-Dec-86 22:30:13 EST
Date: Mon, 22 Dec 86 22:29 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: DECLARE option to DEFGENERIC(-OPTIONS)
To: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <861219235343.2.MOON@EUPHRATES.SCRC.Symbolics.COM>,
The message of 20 Dec 86 15:43 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>,
<861222-120233-8937@Xerox>,
The message of 22 Dec 86 16:10 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861222222945.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Thanks, Dick, for the explanation of the FTYPE declaration and the
FUNCTION type-specifier. Now that I understand what these do and
don't do, I'm of the opinion that we should remove all mention of
them from our document.
Everyone seems to agree that (DECLARE (OPTIMIZE ...)) should be
allowed.
The next question is whether declarations in a DEFGENERIC-OPTIONS should
be propagated to the methods. Currently the spec says no, but Dick
suggested that it could make sense. Looking at chapter 9 of CLtL, I
think this would only apply to the TYPE declaration (and its abbreviated
forms in Table 4-1) and the IGNORE declaration; the other declarations
either depend on names of arguments (e.g. SPECIAL) or aren't associated
with argument bindings (e.g. INLINE). I'll write the paragraph below
as if this is accepted, but I'm not sure the extra complexity is
justified.
Here is my suggested rewrite of the current text:
The {\bf declare} option is used to specify declarations that pertain
to the generic function. The following standard Common Lisp
declarations are allowed:
- {\bf optimize} specifies whether method selection should
be optimized for speed or space, but has no effect on methods.
To control how a method is optimized, an {\bf optimize} declaration
must be placed directly in the {\bf defmethod}.
{\bf speed} and {\bf space} are the only standard qualities, but
other qualities may be recognized by particular implementations.
A simple implementation that has only one method selection
technique and ignores the {\bf optimize} declaration is valid.
- {\bf type} and its abbreviated forms in Table 4-1 declare type
restrictions on the arguments. Such declarations are automatically
copied into methods, with variable names translated to corresponding
parameter names.
- {\bf ignore} specifies arguments that are never used. Such
declarations are automatically copied into methods, with variable
names translated to corresponding parameter names.
The {\bf special}, {\bf ftype}, {\bf function}, {\bf inline},
{\bf notinline}, and {\bf declaration} declarations are not permitted.
Individual implementations can support their own additional
declarations. If an implementation notices a declaration that it does
not support and that has not been proclaimed as a non-standard
declaration name, it should issue a warning.
Any more comments on this issue? Should the TYPE and IGNORE declarations
be retained or removed?
∂22-Dec-86 2259 masinter.pa@Xerox.COM Re: with-slots & interning of constructed symbols
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Dec 86 22:59:20 PST
Received: from Chardonnay.ms by ArpaGateway.ms ; 22 DEC 86 22:55:30 PST
From: masinter.pa@Xerox.COM
Date: 22 Dec 86 22:53:22 PST
Subject: Re: with-slots & interning of constructed symbols
In-reply-to: Moon@STONY-BROOK.SCRC.Symbolics.COM's message of Mon, 22
Dec 86 20:43 EST, <861222204333.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
To: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
cc: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861222-225530-9409@Xerox>
I wasn't clear.
I think it is important to get a proposal out to the community and the
committee which reflects where this working group has been going with
"objects in common lisp" as soon as possible, and, in particular, in
time for there to be some posssibility that the X3j13 committee can
either endorse it or send it back to subcomittee.
In order to get there, I think we need to converge as soon as possible
on those parts of this thing that are agreeable. In some areas, e.g.,
with with-slots and the prefix option to defclass, we have identified a
design problem, several design alternatives, none of which are entirely
satisfactory. Rather than having the whole proposal balled up behind
with-slots and the package of the prefix option, we can have the March
version not include with-slots in any of its proposed form.
I like the idea of with-slots, its just that it seems less ready than
most of the rest of the proposal. My idea was not to remove it from the
standard, but to acknowledge that it is obviously a syntactic extension
which need not be included in the first release.
I presume that endorsement is the desired outcome of the March meeting,
and that we are all working mutually toward that goal.
∂23-Dec-86 0031 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Comments on the revised function chapter
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 23 Dec 86 00:30:41 PST
Received: from ti-csl by csnet-relay.csnet id ac05500; 23 Dec 86 2:50 EST
Received: from Jenner (jenner.ARPA) by tilde id AA00568; Mon, 22 Dec 86 16:31:44 cst
To: Common-Lisp-Object-System@SU-AI.ARPA
Subject: Comments on the revised function chapter
Date: 22-Dec-86 16:27:51
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2744663268@Jenner>
Defgeneric-options:
It bothers me that the class of a method is determined at the generic function level.
I think that we are forcing too many things in the generic function. See my mail on
method combination selection.
Anyway, if the class of methods has to be constant on a generic function, then it really means
that the generic function knows about the method class. This means that the method class can be
defined as a mixin of the generic function class. Then we could get rid of the :METHOD-CLASS keyword.
make-method:
There is something missing here. How does it know about the method-class? How would the caller
know about choosing the right method-class? Since it depends on the generic-function, the caller
has to know about the generic function he is making the method for. I support David's comment:
"I would think a method object would want to know what generic-function it
was for; another argument should be added."
It seems to be the cleanest solution to this problem.
From David:
"I assume the reason someone is
proposing to change documentation to be object-oriented is because
Common Lisp is defective and doesn't have any names for methods, because
only symbols can be used as names. We could fix that."
DOCUMENTATION is not the only function having to change because methods don't have names.
TRACE will not work either. Giving names to methods (other than phony symbol names) is a
good idea. Then DEFMETHOD could return a name as other DEF forms do.
I am in favor of changing ARGUMENT-PRECEDENCE-ORDER back to an ordered list.
Patrick.
∂23-Dec-86 1018 Bobrow.pa@Xerox.COM Re: with-slots & interning of constructed symbols
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Dec 86 10:18:24 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 23 DEC 86 10:16:13 PST
Date: 23 Dec 86 10:16 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: with-slots & interning of constructed symbols
In-reply-to: masinter.pa's message of 22 Dec 86 22:53:22 PST
To: masinter.pa@Xerox.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM,
Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861223-101613-9652@Xerox>
We don't have to agree completely for the committee. If we have a place
where there is the need for a better idea, and a reasonable one to
start, (e.g. with-slots) then opening the discussion up to the community
is a good idea. I believe that things will be approved in pieces
anyway, and as consensus on parts are reached, people will provide
implementations and use those parts. Peripheral features will be used
later. Things sent back to subcommittee will only details.
This is not to take away from the need to converge on as many parts of
the standard as we can. Hoever, it might be good tactics to have clear
places for all those people to argue about -- allowing the central
features to be immediately accepted as being so much better. Whoops --
sorry for the cynicism.
I expect the outcome of the net discussion preceding the March meeting
(for X3J13) to be a series of issues that will have to be addressed in
the rationale document, and that the March meeting will be an overall
endorsement with some open questions remaining.
danny
∂23-Dec-86 1310 skeene@STONY-BROOK.SCRC.Symbolics.COM documentation revised
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Dec 86 13:10:02 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 30439; Tue 23-Dec-86 16:01:00 EST
Date: Tue, 23 Dec 86 15:59 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: documentation revised
To: common-lisp-object-system@SU-AI.ARPA
Message-ID: <861223155958.0.SKEENE@JUNCO.SCRC.Symbolics.COM>
I wrote a new version of the concepts.tex file. I filled in a lot of
the blank spots, did some rewriting, and tried to TEX-ify the parts that
were in plain text format. When it is next formatted you may find TEX
inconsistencies that will need fixing.
My impression of the current documentation status is: The function
chapter is looking quite solid. The concepts chapter is getting
there, but needs a lot of work. The design rationale chapter needs
even more work.
When I was reading and revising the concepts chapter, I found some of
the terminology a real stumbling block. Terminology is important. A
term is supposed to shed some light on the concept it names. We've got
to try harder here. Here are some of the terms that the document
currently uses:
CLASS: a predefined class that is the default metaclass. The class of
CLASS is CLASS.
Standard class: an object whose class is CLASS.
OBJECT: a predefined class that is a component of all objects whose
class is CLASS (that is, a component of all standard classes).
Standard object: an object whose metaclass is CLASS; all standard
objects include the class OBJECT as a component.
STANDARD-TYPE-CLASS: this class is a component of all classes that
correspond to a predefined Common Lisp type specifier. The term
"standard-type-class" is used informally to mean a class that has
the component STANDARD-TYPE-CLASS.
The design rationale chapter currently contains a few sections
discussing very specific points. Are we going to try to give rationale
at a higher level? There was an interesting message that came across
this mailing list awhile back, that mentioned a lot of possible places
where this proposal will be criticised. One of the points was how
large the spec is. Other people responded to that message. Maybe we
should start to address these kinds of points in the design rationale
chapter.
∂23-Dec-86 1327 Gregor.pa@Xerox.COM Re: Uninitialized Slots
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Dec 86 13:27:19 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 23 DEC 86 13:27:41 PST
Date: 23 Dec 86 13:27 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Uninitialized Slots
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 17 Dec 86
21:10 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861223-132742-9809@Xerox>
Moon:
A standard that specifies that the contents of an
uninitialized slot is complete garbage and the ONLY thing about
it that is guaranteed is that reading it will NOT signal an
error doesn't appeal to me.
Gabriel:
As long as the stock hardware guys can write compilers that
omit the check with a certain safety level setting, there is no
problem with `signals' versus `is' for me.
...
This code is ok under the undefined case, because it
doesn't matter what the value is (as long as it is an existent Lisp
object) - it only matters that it isn't this Lisp object carefully
created to be different from any others.
I think Dick's example makes it clear that it would be reasonable for us
to say that the value of an unitialized slot was undefined, but
guaranteed to be a "legal pointer". On the other hand, I would be
willing to make it "signals an error" with the caveat Dick mentions of
being able to skip the check under certain speed and safety conditions.
So I guess this means its fine with me if we go back to letting this
work "the same way as unbound special variables".
∂23-Dec-86 1429 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Relationship between accessors and methods
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 23 Dec 86 14:28:48 PST
Received: from ti-csl by csnet-relay.csnet id ap03343; 23 Dec 86 16:38 EST
Received: from dsg (juliett.ARPA) by tilde id AA27372; Tue, 23 Dec 86 14:45:10 cst
Received: FROM Jenner BY dsg Via CHAOS-NET with CHAOS-MAIL; 23-Dec-86 14:44:08
Message-Id: <2744743458-1524467@Jenner>
Date: 23-Dec-86 14:44:18
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
To: DavidA%Jenner%ti-csl.csnet@RELAY.CS.NET
Cc: Common-Lisp-Object-System@SU-AI.ARPA
Subject: Re: Relationship between accessors and methods
In-Reply-To: In-Reply-To: Msg of 17-Dec-86 23:18:00 from David A@JennerMsg of 17-Dec-86 23
Date: 17-Dec-86 23:18:00
From: David A Moon.
Moon: The relationship between accessors (methods created with
:accessor, :reader, :accessor-prefix, and :reader-prefix) and
regular methods (created with defmethod) needs to be discussed.
One issue is how they combine, e.g. (defmethod-setf foo-slot :after
((object foo)) (new-value) ...). Another is what happens if you
define a conflicting regular method, e.g. (defmethod-setf foo-slot
((object foo)) (new-value) ...) when (defclass foo () ((slot
:accessor foo-slot))) has been done.
Gregor: Right. I believe the way to make this clear is to specify that the
accessor methods are regular methods, they behave as if they were
defined by a defmethod, e.g.
(defmethod foo-slot ((foo foo)) (slot-value foo 'slot))
This isn't what we do in Flavors now, but after thinking this over for
some time I believe what you suggest is desirable. I think we would use
a different class of method-object for accessors, so it wouldn't behave
precisely the same as that defmethod. However, it would have the key
property that if you define both a regular method and an accessor, for
the same generic function and the same class, with no method qualifiers,
whichever one you define second replaces whichever one you define first.
It would also have the key property that in method combination it
behaves just like the defmethod. The difference from the defmethod
would be purely internal to the implementation, unless you examined the
type-of the method-object.
I think the Functions chapter of the documentation should be augmented
with a note, in the defclass section, explaining this quite explicitly.
(Not talking about Symbolics' or anybody else's implementation, of
course.)
What you propose could be expressed another way:
"Methods created for accessors don't necessary belong to the default
method Class "METHOD", but to another method class. [i.e it conforms to
the metaclass protocol defined for a method class.]"
This raises (again) the issue of specifying a class for a method.
What you say makes me think that make-method should have a :class
keyword which specifies the method class DEFGENERIC-OPTIONS should be
changed to something like this:
The :method-class option may be used to specify that the default method
class for this generic function is different from the default provided
by the system (the class "METHOD"). The class-name argument is the name of
a class that is capable of being the class of a method.
If the metaclass protocol is well designed, then the generic function
object should be able to deal with non uniform method classes as long as
all of them implement the metaclass protocol properly.
Once we get that straight, I'm not sure that David's note is so
essential. It might be worth adding so people get to think about the
implication of having a metaclass protocol in familiar terms.
Patrick.
∂23-Dec-86 1451 Gregor.pa@Xerox.COM Re: DECLARE option to DEFGENERIC(-OPTIONS)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Dec 86 14:48:08 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 23 DEC 86 14:48:05 PST
Date: 23 Dec 86 14:47 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: DECLARE option to DEFGENERIC(-OPTIONS)
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 22 Dec 86 22:29 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861223-144805-1006@Xerox>
I think the complexity of copying and translating the type and ignore
declarations is more than its worth. In addition, it has a sense of
violating lexical scoping I don't really like.
I don't feel very strongly about this though.
∂23-Dec-86 1457 Gregor.pa@Xerox.COM Re: Comments on the revised function chapter
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Dec 86 14:52:32 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 23 DEC 86 14:52:44 PST
Date: 23 Dec 86 14:36 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Comments on the revised function chapter
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 18 Dec 86 15:26 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861223-145244-1013@Xerox>
Gregor:
Right, I should have said we need to specify, not decide.
Specifically, we need to flesh out the details and spec out
that:
(defmethod-setf foo ((x boat) (y plane) ..) ((nv gasoline)) ...)
becomes *something* like:
(defmethod |foo setf| ((nv gasoline) (x boat) (y plane) ..) ...)
(defsetf foo |foo setf|)
Moon:
I don't understand why any of this has to be specified. This
is purely implementation detail; all that's necessary for the
language specification is to say that the correct information is
communicated to setf. Even at the meta-object level it would be
better to abstract this out of sight e.g. by doing it with
implementation-supplied methods on essential-method.
I think it has to specified so that I can add methods to the setf
generic function using add-method. Here is an example (I will try to
avoid bugs this time):
;;;
;;; Speed is a generic function which returns the speed in MPH of
;;; a moving object, it is setf-able.
;;;
(defgeneric speed (moving-object))
(defgeneric-setf speed (moving-object new-value))
(defclass plane () (mph))
(add-method 'speed
(make-method ()
(list (class-named 'plane))
#'(lambda (p) (slot-value p 'mph))))
(add-method (get-setf-generic-function 'speed)
(make-method ()
(list (class-named 't) (class-named 'plane))
#'(lambda (nv p) (setf (slot-value p 'mph)
nv))))
I admit this example is somewhat contived since for this case I would
obviously use defmethod and defmethod-setf, but I believe it makes the
"programmatic" case it is trying to illustrate clear.
∂23-Dec-86 1729 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Relationship between accessors and methods
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Dec 86 17:29:02 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 30623; Tue 23-Dec-86 20:25:12 EST
Date: Tue, 23 Dec 86 20:24 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Relationship between accessors and methods
To: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
cc: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <2744743458-1524467@Jenner>
Message-ID: <861223202452.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 23-Dec-86 14:44:18
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Date: 17-Dec-86 23:18:00
From: David A Moon.
Gregor: Right. I believe the way to make this clear is to specify that the
accessor methods are regular methods, they behave as if they were
defined by a defmethod, e.g.
(defmethod foo-slot ((foo foo)) (slot-value foo 'slot))
This isn't what we do in Flavors now, but after thinking this over for
some time I believe what you suggest is desirable....
I think the Functions chapter of the documentation should be augmented
with a note, in the defclass section, explaining this quite explicitly.
....
If the metaclass protocol is well designed, then the generic function
object should be able to deal with non uniform method classes as long as
all of them implement the metaclass protocol properly.
Once we get that straight, I'm not sure that David's note is so
essential. It might be worth adding so people get to think about the
implication of having a metaclass protocol in familiar terms.
The issue that I claimed should be explained quite explicitly is not what
class the method object is, but how accessors interact with ordinary methods.
I wasn't trying to get down to the meta-object level at all; it's probably
unnecessary for the defclass section to speak about method classes and
metaclass protocol.
∂24-Dec-86 1502 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Comments on the revised function chapter
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 24 Dec 86 15:02:25 PST
Received: from ti-csl by csnet-relay.csnet id al00580; 24 Dec 86 17:34 EST
Received: from dsg (juliett.ARPA) by tilde id AA15347; Wed, 24 Dec 86 11:01:00 cst
Received: FROM Jenner BY dsg Via CHAOS-NET with CHAOS-MAIL; 24-Dec-86 10:59:36
Message-Id: <2744816552-724350@Jenner>
Date: 24-Dec-86 11:02:32
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
To: Danny Bobrow <Bobrow.pa@XEROX.COM>
Cc: Common-Lisp-Object-System@SU-AI.ARPA
Subject: Re: Comments on the revised function chapter
In-Reply-To: In-Reply-To: Msg of 22-Dec-86 15:57:00 from Danny Bobrow <Bobrow.pa@Xerox.COM>Msg of 22-Dec-86 15
Date: 22-Dec-86 15:57:00
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The class of methods does not have to be constant on a generic function.
The :METHOD-CLASS option only specifies the class to be used for methods
constructed using DEFMETHOD. Using ADD-METHOD, any compatible method
type can be added to a generic function.
I like that, The :method-class bullet of DEFGENERIC-OPTIONS
needs to be rephrased though.
make-method: There is something missing here. How does it know
about the method-class?
This is used only to make methods of type METHOD. Otherwise we can
create other classes of methods using
(make-instance <other-method-class>).
It should be stated clearly in the document. But then I don't see why
make-method is in this chapter since defmethod is the toplevel form to
define a method and make-method can't even be used to make a default
method for a generic function having a :method-class option (unless we
add a way to specify the generic function we are making the method for).
DOCUMENTATION is not the only function having to change because
methods don't have names. TRACE will not work either. Giving names
to methods (other than phony symbol names) is a good idea. Then
DEFMETHOD could return a name as other DEF forms do.
Having a name, and printing so the user can understand are two different
operations. Methods should certainly know how to print themselves for
readability. And TRACE can be made a generic function that takes a
method object as an argument. The method object can be located from the
generic function using (GET-METHOD <g-f> <specifiers>). This allows
methods on unnamed generic-functions to be traced as well.
I agree that having a name-specs for methods is not essential but it sure
would look nicer. Since David Moon couldn't get them, I will miss them
but not fight for them any longer.
I am in favor of changing ARGUMENT-PRECEDENCE-ORDER back to an
ordered list.
After thinking again, I too favor this unchange.
danny
Patrick.
∂24-Dec-86 1504 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: DECLARE option to DEFGENERIC(-OPTIONS)
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 24 Dec 86 15:04:11 PST
Received: from ti-csl by csnet-relay.csnet id ap00580; 24 Dec 86 17:37 EST
Received: from Jenner (jenner.ARPA) by tilde id AA19008; Wed, 24 Dec 86 14:23:17 cst
To: Dick Gabriel <RPG@SU-AI.ARPA>
Cc: common-lisp-object-system@SU-AI.ARPA
Subject: Re: DECLARE option to DEFGENERIC(-OPTIONS)
Date: 24-Dec-86 14:25:32
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2744828729@Jenner>
From Dick:
Many people don't have a correct understanding of the weak nature of FTYPE
specifiers. I've felt that there should be a stronger general form that
states that the arguments must be at most as specified.
I think there are two issues associated with function declaration:
If we use an argument as a functional, then we have to declare it to accept at least...
(defun foo (fun arg)
(declare (ftype (function (string) t) fun))
(funcall fun (symbol-name arg)))
The compiler can do useful checking on the call to foo when fun is a constant.
I think that was the motivation for the ftype thing.
The second issue is proclamation of the type of a function which is not adequately
addressed by CLtL.
Patrick.
∂24-Dec-86 1506 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Comments on the revised function chapter
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 24 Dec 86 15:05:06 PST
Received: from ti-csl by csnet-relay.csnet id as00580; 24 Dec 86 17:38 EST
Received: from Jenner (jenner.ARPA) by tilde id AA19360; Wed, 24 Dec 86 14:41:16 cst
To: Gregor Kiczales <Gregor.pa@XEROX.COM>
Cc: Moon@SCRC-STONY-BROOK.ARPA, Common-Lisp-Object-System@SU-AI.ARPA
Subject: Re: Comments on the revised function chapter
Date: 24-Dec-86 14:43:32
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2744829808@Jenner>
From Gregor:
Gregor:
Right, I should have said we need to specify, not decide.
Specifically, we need to flesh out the details and spec out
that:
(defmethod-setf foo ((x boat) (y plane) ..) ((nv gasoline)) ...)
becomes *something* like:
(defmethod |foo setf| ((nv gasoline) (x boat) (y plane) ..) ...)
(defsetf foo |foo setf|)
Moon:
I don't understand why any of this has to be specified. This
is purely implementation detail; all that's necessary for the
language specification is to say that the correct information is
communicated to setf. Even at the meta-object level it would be
better to abstract this out of sight e.g. by doing it with
implementation-supplied methods on essential-method.
I think it has to specified so that I can add methods to the setf
generic function using add-method. Here is an example (I will try to
avoid bugs this time):
;;;
;;; Speed is a generic function which returns the speed in MPH of
;;; a moving object, it is setf-able.
;;;
(defgeneric speed (moving-object))
(defgeneric-setf speed (moving-object new-value))
(defclass plane () (mph))
(add-method 'speed
(make-method ()
(list (class-named 'plane))
#'(lambda (p) (slot-value p 'mph))))
(add-method (get-setf-generic-function 'speed)
(make-method ()
(list (class-named 't) (class-named 'plane))
#'(lambda (nv p) (setf (slot-value p 'mph)
nv))))
I admit this example is somewhat contived since for this case I would
obviously use defmethod and defmethod-setf, but I believe it makes the
"programmatic" case it is trying to illustrate clear.
Since Add-method accepts eiter a generic-function object or a symbol naming a generic-function,
Your example will work if get-setf-generic-function returns an object.
Patrick.
∂24-Dec-86 1504 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: specializers list
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 24 Dec 86 15:03:53 PST
Received: from ti-csl by csnet-relay.csnet id ao00580; 24 Dec 86 17:36 EST
Received: from Jenner (jenner.ARPA) by tilde id AA18313; Wed, 24 Dec 86 13:43:18 cst
To: Gregor Kiczales <Gregor.pa@XEROX.COM>
Cc: Moon@SCRC-STONY-BROOK.ARPA, Common-Lisp-Object-System@SU-AI.ARPA
Subject: Re: specializers list
Date: 24-Dec-86 13:45:36
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2744826332@Jenner>
Date: 17-Dec-86 18:53:00
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: specializers list
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
Cc: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: In-Reply-To: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s message of Wed, 17 Dec 86 19:04 ESTDavid A
Date: Wed, 17 Dec 86 19:04 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Issue #1 isn't directly addressed by the current spec, but it
implies that the answer is type-specifiers since it mentions a list
of t's. I mildly prefer type-specifiers, but don't see how this
fits in with the idea of unnamed classes. I expect this connects
to the open issue of make-class. At present I have no proposal
on this issue.
Yes, this does connect with the open issue of make-class in the sense
that methods need to be specified for anonymous classes. This meants
that these type specifiers need to be class objects or (QUOTE datum).
In PCL, there is one version of add-method with takes type specifiers,
it turns around and calls another version with the class objects. I
think just the one with the class objects should be enough for the
standard.
How about saying that these type specifiers can be class-names, a classes or
(QUOTE datum)?
I offer the following proposal for issue #2, to replace what
the spec says now (italics and boldface are omitted):
The specializers argument is an association list with one
element for each specialized parameter. Each element is a list,
(pos type), where ...
If we have class objects as the type specifiers then why not just use
the regular lambda list keyword sort of syntax for dealing with
optionals and keys.
so that
(defmethod foo ((x boat) (y plane)) ..)
corresponds to
(#<Class boat 123> #<Class plane 456>)
and later if we add optionals,
(defmethod bar ((c class) &optional (n symbol)) ..)
(#<Class class 789> &optional #<Class symbol 987>)
and keys:
(defmethod baz ((c class) &key (s symbol)) ..)
(#<Class class 789> &key (:s #<Class symbol 987>))
I think Gregor proposal will also work. I mildly prefer David's because the list
is more uniform thus easier to work on.
Patrick.
∂28-Dec-86 1358 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: DECLARE option to DEFGENERIC(-OPTIONS)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Dec 86 13:58:43 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 31385; Sun 28-Dec-86 16:57:49 EST
Date: Sun, 28 Dec 86 16:57 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: DECLARE option to DEFGENERIC(-OPTIONS)
To: common-lisp-object-system@SU-AI.ARPA
In-Reply-To: <DUSSUD.2744828729@Jenner>
Message-ID: <861228165704.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 24-Dec-86 14:25:32
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
From Dick:
Many people don't have a correct understanding of the weak nature of FTYPE
specifiers. I've felt that there should be a stronger general form that
states that the arguments must be at most as specified.
I think there are two issues associated with function declaration:
If we use an argument as a functional, then we have to declare it to accept at least...
(defun foo (fun arg)
(declare (ftype (function (string) t) fun))
(funcall fun (symbol-name arg)))
The compiler can do useful checking on the call to foo when fun is a constant.
I think that was the motivation for the ftype thing.
No, this should be a TYPE declaration, not an FTYPE declaration. You're
declaring the variable-binding of the name fun, not the function-binding of it.
However, I think you're right that this is why the FUNCTION type-specifier
is defined to be so weird.
The second issue is proclamation of the type of a function which is not adequately
addressed by CLtL.
Yes. I mistakenly thought that FTYPE or FUNCTION used as a proclamation could
be used to proclaim the type of a function, but I was wrong. I agree that it
isn't adequately addressed by CLtL.
∂28-Dec-86 1419 Moon@STONY-BROOK.SCRC.Symbolics.COM make-method issue
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Dec 86 14:19:50 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 31393; Sun 28-Dec-86 17:18:57 EST
Date: Sun, 28 Dec 86 17:18 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: make-method issue
To: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <2744816552-724350@Jenner>
Message-ID: <861228171810.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
[portions of Patrick's message dealing with other issues deleted]
Date: 24-Dec-86 11:02:32
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Date: 22-Dec-86 15:57:00
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
make-method: There is something missing here. How does it know
about the method-class?
This is used only to make methods of type METHOD. Otherwise we can
create other classes of methods using
(make-instance <other-method-class>).
It should be stated clearly in the document. But then I don't see why
make-method is in this chapter since defmethod is the toplevel form to
define a method and make-method can't even be used to make a default
method for a generic function having a :method-class option (unless we
add a way to specify the generic function we are making the method for).
This was my reaction also. If make-method isn't the functional version
of what defmethod does, and isn't to be used by users who make their own
classes of methods, then who would ever use it? Another way of looking
at this is that I had hoped we would have a layered presentation,
consisting of the basic programmer interface, the functional versions of
those macros, and the meta-object protocol underlying those functions.
These three layers are aimed at three different clases of users. I
don't see where make-method as currently defined fits into this schema.
If people are supposed to use make-instance, rather than make-method, to
make methods, then we should document the arguments to make-instance to
be used for that purpose. Having done that, there doesn't seem to be
any reason to retain make-method.
This may be hung up on defining the initialization protocol. I've been
looking into that and hope to have an opinion this week.
∂28-Dec-86 1426 Moon@STONY-BROOK.SCRC.Symbolics.COM :method-class option to DEFGENERIC-OPTIONS
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Dec 86 14:24:15 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 31397; Sun 28-Dec-86 17:23:19 EST
Date: Sun, 28 Dec 86 17:22 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: :method-class option to DEFGENERIC-OPTIONS
To: SKeene@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <2744816552-724350@Jenner>
Message-ID: <861228172235.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
[portions of Patrick's message dealing with other issues deleted]
Date: 24-Dec-86 11:02:32
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Date: 22-Dec-86 15:57:00
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The class of methods does not have to be constant on a generic function.
The :METHOD-CLASS option only specifies the class to be used for methods
constructed using DEFMETHOD. Using ADD-METHOD, any compatible method
type can be added to a generic function.
I like that, The :method-class bullet of DEFGENERIC-OPTIONS
needs to be rephrased though.
Agreed; right now it says "to specify that all methods for
this generic function are to have a different class than the default".
It should instead say something about changing the class of methods
made by DEFMETHOD; I don't know if that should be called the "default
class of methods for this generic-function" or not. Sonya, can you
take care of this?
∂28-Dec-86 1557 Moon@STONY-BROOK.SCRC.Symbolics.COM terminology confusion
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Dec 86 15:56:51 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 31414; Sun 28-Dec-86 18:55:59 EST
Date: Sun, 28 Dec 86 18:55 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: terminology confusion
To: common-lisp-object-system@SU-AI.ARPA
In-Reply-To: <861223155958.0.SKEENE@JUNCO.SCRC.Symbolics.COM>,
<861219214330.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <861228185506.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
I've been thinking about the terminology issues that Sonya brought up.
I think a lot of the present confusion comes from the fact that people
intuitively expect the English phrase "foo is a bar" and the Lisp
expression (TYPEP FOO 'BAR) to be equivalent, yet the current
terminology violates this expectation. A good example is CLASS, which
you would expect to be the class of all classes, but instead is merely
the class of classes made by DEFCLASS without a :metaclass option. Thus
the English phrase "foo is a class" is equivalent to some Lisp
expression like (TYPEP foo 'SI:ESSENTIAL-CLASS), and there is no
non-clumsy English equivalent to the Lisp expression (TYPEP foo 'CLASS).
You can see how confusing all this is.
I propose we adopt as our first principle that "foo is a bar" and
(TYPEP FOO 'BAR) shall be equivalent. This immediately implies that
CLASS, METHOD, and GENERIC-FUNCTION are abstract classes, the classes of
all such objects. We need different names for the classes used
by default by the basic programmer interface. I suggest STANDARD-CLASS,
STANDARD-METHOD, and STANDARD-GENERIC-FUNCTION. This makes the phrase
"foo is a standard class" mean exactly what one thinks it means.
The only problem I see with the use of the word "standard" is that
someone might think a "standard class" is a class that is documented in
CLtL (or a future standard); when we say "foo is a standard class" we
mean that "the class foo behaves in a standard way", not "instances of
foo behave in a standard way". In other words, it is the metaclass
whose methods are standardized, not the class. I think this is okay. I
considered DEFAULT-CLASS instead of STANDARD-CLASS, but concluded that
it would be definitely more confusing.
The next problematic term is OBJECT, which now means an instance of an
instance of CLASS, or, with my suggestion, an instance of an instance of
STANDARD-CLASS. Intuitively one expects OBJECT to mean any object, i.e.
an instance of T. I suggest that the class of all instances whose
metaclass is STANDARD-CLASS be named either STANDARD-OBJECT or
STANDARD-INSTANCE. I like STANDARD-INSTANCE a little better. I haven't
been able to figure out whether this class needs to be documented or is
only an internal implementation detail.
STRUCTURE-CLASS already fits my proposed principle.
STANDARD-TYPE-CLASS is a problematical term in multiple ways. I propose
eliminating this concept of the class of all classes that are defined by
the book CLtL. The important concept that STANDARD-TYPE-CLASS was
trying to capture was the class of all classes that cannot be subclassed
and can only be instantiated by some means other than MAKE-INSTANCE. A
better name for this, and the one we were using in most of the mail that
I reviewed, was BUILT-IN-CLASS. An object whose implementation is built
into the Lisp implementation, rather than being done through DEFCLASS,
has BUILT-IN-CLASS as a meta-class. A built-in class cannot be
instantiated with MAKE-INSTANCE and cannot have new subclasses defined.
This raises an important point. Some of the common classes (the ones
defined by CLtL) will be implemented in different ways in different
implementations. Pathnames are a good example. Some implementations
define PATHNAME as a built-in class; maybe they say that if the low 3
bits of the object reference are 101 and the high 4 bits are 0010, the
object is a pathname, and its storage layout consists of seven words
defined thus-and-so. Other implementations define PATHNAME as a
structure class; they don't have pathnames built into their system at
the lowest level, but instead they have a preloaded module that includes
a Lisp form (defstruct pathname host device directory name type version).
Still other implementations define PATHNAME as a standard class; they
have a preloaded module that includes a Lisp form something like
(defclass pathname () (host device directory name type version)).
Such implementations might well define subclasses of pathname, using
defclass. This is how ours works, for example.
The standard should not rule out any of these implementation techniques;
it should say that classes corresponding to types defined in CLtL are
permitted to be built-in classes, but not required to be built-in
classes. Thus portable programs cannot make subclasses of such classes,
but also cannot rely on an error being signalled if they attempt to make
a subclass. Taking pathnames as an example again, in our implementation
it's perfectly legal, but not portable, to make a subclass of PATHNAME.
That's how we are able to access files on SU-AI conveniently, for
instance; we load a program that among other things creates a new
subclass of PATHNAME that uses WAITS (SU-AI's operating system)
conventions. It would be silly to say that this program can't be
written using DEFCLASS, and we have to make up a special
DEFCLASS_INTERNAL for it to use that bypasses the portability check.
The program isn't trying to be portable. I assume the same issue will
arise in other implementations and for other common classes.
Issue: is STRUCTURE-CLASS a subtype of BUILT-IN-CLASS? In favor:
structure classes have the properties of being instantiated a special
way and not being subclassable with DEFCLASS. Opposed: the user can
define new structure classes but only the Lisp implementor can define
new built-in classes, also structure classes are subclassable, using the
:include option to defstruct. My answer is "no" but other opinions are
welcome.
One last terminology issue, somewhat separate from the above:
We need consistent terminology for distinguishing between the direct
parents of a class and the transitive closure of parentage; similarly
in the child direction. Right now the document sometimes uses "superclass"
and "subclass" to mean only the directly related classes, and uses
"component" to mean "superclass↑n, 0<=n" and "dependent" to mean
"subclass↑n, 0<=n". In other places the document uses "superclass" to
mean the transitive closure and "direct superclass" to mean the directly
related classes, and similarly for "subclass" and "direct subclass".
We need to be consistent about this. I believe the component/dependent
terminology is clearer, because it avoids using a single word to mean
two things, but other opinions are welcome.
I have raised a number of issues and for each one proposed a solution.
Are there any objections to any of the proposed solutions? If so, are
there any objections to the overall approach? Let's resolve this soon!
The second message referenced in the in-reply-to field was a private
message from me to Sonya. What I said in there was somewhat
contradictory to this message, and is superseded (nine additional days
of thinking it over produced different conclusions).
∂28-Dec-86 1618 Moon@STONY-BROOK.SCRC.Symbolics.COM MAKE-METHOD arguments discussion
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Dec 86 16:18:26 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 31425; Sun 28-Dec-86 19:17:30 EST
Date: Sun, 28 Dec 86 19:16 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: MAKE-METHOD arguments discussion
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861228191645.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Moon: I would think a method object would want to know what
generic-function it was for; another argument should be added. It
at least wants to know this for purpose of printing out.
Gregor: Our thought was that a method could be on more than one generic
function.
I see. Maybe that can really work; so far I haven't been able to convince
myself one way or the other. However, I still think a method object
should be able to print something reasonable, even if it's only a hint.
Given that MAKE-METHOD is being flushed in favor of MAKE-INSTANCE of the
desired method-class, we can make this information optional.
Moon: What are the requirements on the function: arguments, results,
and environment for call-next-method? I prefer that only functions
that have been blessed by the generic-function meta-object before
being compiled be allowed. I suppose we could allow any function
here with naive arguments, but then we just have to have
MAKE-METHOD-REAL, which is the one DEFMETHOD really uses.
I forgot to mention that I don't see how the capability of WITH-SLOTS to
determine the class of an instance-form by looking at the defmethod
lambda-list can be implemented without blessing the function. Or is that
a feature that only works inside defmethod and isn't available to users
making their own methods at the make-method level?
Gregor: As I said before, I don't believe the function should have to be
blessed. In the implementation I have in mind, we would not need to
bless the function and also not have to have make-method-real. I think
even for implementations which choose to have blessed functions it is a
misfeature to push this blessing in the user's face, it should be behind
the scenes.
So you have one implementation in mind and I have another. That's no
surprise. I believe the standard should not have one particular
implementation wired into it. If it's going to be successful and widely
adopted, there will probably be at least half a dozen implementations,
each optimized for different goals.
The particular issue of the requirements on method functions may be
moot, since MAKE-METHOD is already not a functional equivalent of
DEFMETHOD (which I hadn't realized at the time I wrote my comments
quoted above). DEFMETHOD will want to instantiate an appropriate class
of method that is optimized for the implementation. I haven't seen
proposals for the meta-object protocol, but I assume that the
meta-object protocol will allow method-class dependent transformation of
the method function. Users who are trying to do something simple and
not optimized, and don't want to get down to the meta-object layer, but
do want to get down to the functional layer underlying the defmethod
macro, can be given a method class that accepts ordinary functions.
That should make everybody happy. An alternative protocol that might
work better would be for the standard method-classes to accept both, and
to use two different init keywords, one for ordinary functions and the
other for blessed functions.
∂28-Dec-86 1656 RPG Question about MAKE-METHOD Arguments
To: common-lisp-object-system@SAIL.STANFORD.EDU
To Dave Moon:
Besides printing of methods and the proper working of programming tools,
are there any other reasons for a method object to know (have a pointer to)
its generic function?
To Gregor:
When you state that the same ``method could be on (sic) more than one
generic function,'' does this preclude different method objects sharing
the same underlying method function? That is, would it be ok to have the
method object know the generic function it is part of, but not the method
function (which is the meat of the method object)? Do you envision
glueing method objects in a variety of generic functions?
-rpg-
∂28-Dec-86 1807 Moon@STONY-BROOK.SCRC.Symbolics.COM Question about MAKE-METHOD Arguments
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Dec 86 18:06:58 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 31452; Sun 28-Dec-86 21:05:56 EST
Date: Sun, 28 Dec 86 21:05 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Question about MAKE-METHOD Arguments
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 28 Dec 86 19:56 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861228210505.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 28 Dec 86 1656 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Besides printing of methods and the proper working of programming tools,
are there any other reasons for a method object to know (have a pointer to)
its generic function?
It's hard to say without knowing how the meta-object protocol will
organize things. For guidance, I surveyed all callers of the
function that gets from Flavors' equivalent of a method object to the
generic function (actually, to the name of the generic function).
The breakdown is somewhat subjective, but I found:
1 maintaining the slot
20 programming tools (includes printing)
12 to save passing it (or a list of them parallel to another list) in as
a separate argument to "object oriented" operations on methods.
2 debugger program-state analysis
7 irrelevant to CLOS
It's difficult to draw any conclusions from this. Each of those 12 might
be a reason for method objects to know their generic function, or might
merely be something that would have to be implemented a different way.
One would have to do a careful study to determine which they are, and
the result for some of them would be strongly affected by the particular
meta-object protocol chosen.
I will say that there were considerably more dependencies on the
method-to-generic-function link than I had expected when I started.
∂28-Dec-86 2040 Moon@STONY-BROOK.SCRC.Symbolics.COM Note to go into the Concepts chapter
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Dec 86 20:39:55 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 31481; Sun 28-Dec-86 23:39:03 EST
Date: Sun, 28 Dec 86 23:38 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Note to go into the Concepts chapter
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861228233818.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
In the meeting in Portland on 29 September we noted: we will recommend
that compiling a file with defclass, defmethod forms in it should not
side-effect the world in which the compiler is running, but we won't
require it. This was "to avoid portability problems from 2 different
implementations doing it different ways"; I didn't write down what the
portability problems discussed were. This caveat should be extended to
defgeneric-options, defgeneric-options-setf, defmethod-setf, and
define-method-combination forms as well. The general idea is that when
the compiler sees one of these forms, it has to remember information
derived from that form for use in compiling later forms. For example,
it has to remember the slots declared in a defclass so it can compile
methods that do with-slots for instances of that class. The easy way
to do this is just to evaluate the form, but that is very bad because
it can make it impossible to compile programs that have had incompatible
changes made to them and are loaded into the world where the compiler
is running. A better implementation keeps the name-to-object bindings
for classes (and other CLOS objects) separate for the compile-time
environment and the run-time environment.
The above note should be rewritten in English and put into the Concepts
chapter, or wherever it belongs.
∂28-Dec-86 2112 Moon@STONY-BROOK.SCRC.Symbolics.COM :allocation slot-option issues
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Dec 86 21:12:45 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 31485; Mon 29-Dec-86 00:11:51 EST
Date: Mon, 29 Dec 86 00:11 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: :allocation slot-option issues
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861229001104.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
(1) The document currently says
If the allocation type is :class, storage for the slot is allocated
in the class object created by the defclass form. The value of
the slot is shared by all instances of the class. Any subclass of this
class will share this single slot unless the defclass form
for that subclass specifies a slot of the same name.
This is okay, but points up an inconsistency between instance-variables
and class-variables. Repeating the slot declaration of an instance
variable does not create two separate slots, but repeating the slot
declaration of a class variable does. I'm sure Alan Snyder would say
that we should change instance variables to do the same as class variables,
but I prefer to wonder if this indicates that something about class
variables is broken.
Several months ago I remember we discussed splitting :allocation :class
into :allocation :per-class and :allocation :shared (or some names like
that) to address this problem. :per-class slots get a new copy for each
dependent subclass, whereas :shared slots are shared among all dependent
subclasses, even if the slot declaration is repeated. I think either the
discussion was before this group got started or else it quickly dropped
out of sight; I can't find it in any mail archives. Can we open this
issue and discuss the pros and cons of making this change?
. . . . . . . . . . . . . . .
(2) Moon: The :dynamic and :none allocation-types are hacks and should be
removed. In Menlo Park we spent a long time talking about the
weirdness of dynamic allocation, and my conclusion from that is
that it doesn't belong in the standard. I have no problems with
:instance and :class allocation.
Gregor: :dynamic and :none are not hacks. My recollection from
Menlo Park is that the concern was over undeclared dynamic slots
not declared ones. We spent some time talking about whether there
should be some function (perhaps get) which should create :dynamic
slots on the fly. We weren't sure about this. But I thought we
all agreed that declared :dynamic slots were reasonable.
We can play "yes it is / no it isn't" until we're blue in the face and
not convince anybody. The reason why I say they are hacks is that they
have no semantic significance (with the exception that any side-effects
incurred by the default-value form happen at a different time in
:allocation :dynamic, or not at all in :allocation :none); they only
control the amount of storage consumed by an instance, not the way an
instance behaves. :allocation :class is very different; it has true
semantic effect. Thought experiment: consider an implementation that
treated :allocation :dynamic and :allocation :none as synonyms for
:allocation :instance; how could a user distinguish this implementation?
My notes on the discussion of dynamic slots at the Menlo Park meeting
just say we had a lot of discussion that I didn't write down,
culminating in tabling the issue, so I can't be sure now whether we
brought up declared dynamic slots or not. I don't think I would have
agreed, if asked, that they were reasonable.
Can anyone present examples of "real life" uses of :allocation :dynamic
and :allocation :none? If you can, I might change my tune, but otherwise
I propose to remove them from the standard.
. . . . . . . . . . . . . . .
This is the last of the messages I promised to send, discussing
individual issues raised by Gregor's comments on my comments on the
Function chapter. Note that there are some other issues that need
to be resolved, but where I didn't have an opinion to offer. Sonya
mailed out a list at the time she updated the Function chapter.
I propose to wait a week (i.e. until 5 January) for comments to roll in,
then start updating the document for issues where there doesn't seem to
be disagreement. In the interests of time, I'd like to start assuming
that anyone who doesn't speak up agrees, rather than waiting for
everyone to weigh in. If anyone didn't have time to comment, perhaps
due to the holidays, no problem, when they do comment we can revise the
document again or undo changes if necessary.
∂29-Dec-86 1129 RPG Terminology
To: common-lisp-object-system@SAIL.STANFORD.EDU
I propose that we adopt the component/dependent nomenclature that
Moon suggests.
If no one objects, I will edit in those changes to CONCEPTS, soon.
-rpg-
∂29-Dec-86 1201 RPG Standard-type-class
To: common-lisp-object-system@SAIL.STANFORD.EDU
Moon brings up the topic of the name and status of STANDARD-TYPE-CLASS.
The reason that Danny, Gregor, and I decided to rename BUILT-IN-CLASS
to be STANDARD-TYPE-CLASS was precisely because the term ``built-in''
tends to imply that the implementors of the Common Lisp will implement
``built-in'' things directly rather than as DEFSTRUCTs.
The terminology ``STANDARD-TYPE-CLASS'' is intended to be parsed as if it
were ``(STANDARD-TYPE)-CLASS,'' where STANDARD-TYPE is intended to remind
people of the Standard Type Specifier Symbols table on page 43 of CLtL. We
believed that people would want to write code that could distinguish
whether an object was a CLtL entity, but I cannot remember the specific
pieces of code we had in mind at the time.
-rpg-
∂29-Dec-86 1218 Moon@STONY-BROOK.SCRC.Symbolics.COM Issues in Concepts chapter
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Dec 86 12:18:32 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 31983; Mon 29-Dec-86 15:17:14 EST
Date: Mon, 29 Dec 86 15:16 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Issues in Concepts chapter
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <861229151622.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Here is a list of the issues I found in my reading of the 23 Dec version
of the Concepts chapter, omitting typographical and editorial issues.
In most cases this message is just a list of what I think the issues
are, without recommendations for what to do about them. I thought it
was a good idea to send this list now, even if I haven't thought through
the issues, since Dick is currently revising that chapter. I'll
probably send mail at a later time elaborating on some of these issues.
I already sent mail about the terminology issues.
The set of built-in classes and the relationships among those classes
aren't up to date with the latest discussions, I think. Also I'm not
sure if the discussions really converged (I haven't re-read them).
The class precedence rules may be modified, depending on the results of
a discussion that started a few weeks ago but hasn't finished.
Classes aren't really just a lattice, because when a class has multiple
(direct) superclasses, the ordering of the superclasses matters.
Figure 1-2 doesn't contain this information (null and vector are
the affected classes). One way to put this information into the figure
would be to say that multiple superclasses are ordered with the most
specific class highest on the page. If we do this, null is right but
vector is inverted.
Initialization protocol is still to be defined.
Define-method-combination is still to be defined.
We need to define quite explicitly the inheritance behavior of class
options and slot options. It's not true that a slot description
completely overrides any inherited description of the same slot; some
slot options are overridden, some aren't. Similarly, some class options
are overridden, some aren't, and some (e.g. :documentation) aren't
inherited at all. There should be a table listing each option and
showing how it inherits.
∂29-Dec-86 1302 Moon@STONY-BROOK.SCRC.Symbolics.COM Standard-type-class
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Dec 86 13:02:00 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 32060; Mon 29-Dec-86 16:00:58 EST
Date: Mon, 29 Dec 86 16:00 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Standard-type-class
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 29 Dec 86 15:01 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861229160008.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 29 Dec 86 1201 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Moon brings up the topic of the name and status of STANDARD-TYPE-CLASS.
The reason that Danny, Gregor, and I decided to rename BUILT-IN-CLASS
to be STANDARD-TYPE-CLASS was precisely because the term ``built-in''
tends to imply that the implementors of the Common Lisp will implement
``built-in'' things directly rather than as DEFSTRUCTs.
The terminology ``STANDARD-TYPE-CLASS'' is intended to be parsed as if it
were ``(STANDARD-TYPE)-CLASS,'' where STANDARD-TYPE is intended to remind
people of the Standard Type Specifier Symbols table on page 43 of CLtL. We
believed that people would want to write code that could distinguish
whether an object was a CLtL entity, but I cannot remember the specific
pieces of code we had in mind at the time.
I think STANDARD-TYPE-CLASS and BUILT-IN-CLASS are two different things.
STANDARD-TYPE-CLASS is the class of all classes that are defined in the
book CLtL. BUILT-IN-CLASS is the class of all classes that are
implemented in a special non-extensible way. There is a lot of overlap;
for example, in every implementation I know of the class INTEGER is an
instance of both of these classes. However, they aren't the same, which
I think is the source of terminological unclarity. There is also a
subtle distinction between an object having STANDARD-TYPE-CLASS as a
meta-class and (TYPEP object 'COMMON); two examples are a character that
is not a standard-char (most but perhaps not all implementations have
these), which is a meta-instance of STANDARD-TYPE-CLASS but isn't COMMON,
and a type created by the user via DFESTRUCT, which is COMMON but isn't
a meta-instance of STANDARD-TYPE-CLASS.
All these confusions made me suggest eliminating STANDARD-TYPE-CLASS.
However, I have no aversion to keeping STANDARD-TYPE-CLASS if people
think it is useful (it would be nicer if we could remember the specific
example that led to its introduction and put it in the Design Rationale
section). However, STANDARD-TYPE-CLASS doesn't seem to be the right
one to refer to when explaining which classes can't be subclassed or
which classes can't be MAKE-INSTANCEd.
I see two levels at which to think about these various classes. One
is whether they increase or decrease the clarity of the presentation
of the CLOS standard proposal. The other is whether they have a place
in the meta-object protocol.
∂29-Dec-86 1333 RPG STANDARD-TYPE-CLASS
To: common-lisp-object-system@SAIL.STANFORD.EDU
Moon is right, BUILT-IN-CLASS and STANDARD-TYPE-CLASS ought to denote
different things by virtue of their English cognate components, but we had
intended that ``BUILT-IN-CLASS'' misleadingly refer to what we now define
as ``STANDARD-TYPE-CLASS.''
In the absence of the unremembered examples, I would vote to eliminate
this class. Its only purpose would seem to be to enable programmers to
write code that would operate on objects distinguished according to
whether they were part of the implementation of the object-oriented system
or of the underlying Common Lisp.
-rpg-
∂29-Dec-86 1829 Bobrow.pa@Xerox.COM Re: :method-class option to DEFGENERIC-OPTIONS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Dec 86 18:29:29 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 29 DEC 86 17:04:32 PST
Date: 29 Dec 86 17:03 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: :method-class option to DEFGENERIC-OPTIONS
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sun, 28 Dec 86 17:22 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: SKeene@STONY-BROOK.SCRC.Symbolics.COM,
Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861229-170432-2546@Xerox>
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
[portions of Patrick's message dealing with other issues
deleted]
Date: 24-Dec-86 11:02:32 From:
DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Date: 22-Dec-86 15:57:00 From: Danny Bobrow
<Bobrow.pa@Xerox.COM>
The class of methods does not have to be constant
on a generic function. The :METHOD-CLASS option only
specifies the class to be used for methods constructed using
DEFMETHOD. Using ADD-METHOD, any compatible method type can
be added to a generic function.
I like that, The :method-class bullet of
DEFGENERIC-OPTIONS needs to be rephrased though.
Agreed; right now it says "to specify that all methods for this
generic function are to have a different class than the default".
It should instead say something about changing the class of methods
made by DEFMETHOD; I don't know if that should be called the
"default class of methods for this generic-function" or not.
Sonya, can you take care of this?
I agree that this should be described as the "default class of methods
for this generic-function".
danny
∂29-Dec-86 1829 Bobrow.pa@Xerox.COM Re: terminology confusion - component/dependent
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Dec 86 18:29:39 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 29 DEC 86 17:16:04 PST
Date: 29 Dec 86 17:15 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: terminology confusion - component/dependent
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sun, 28 Dec 86 18:55 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861229-171604-2561@Xerox>
We need consistent terminology for distinguishing between the
direct parents of a class and the transitive closure of parentage;
similarly in the child direction. Right now the document sometimes
uses "superclass" and "subclass" to mean only the directly related
classes, and uses "component" to mean "superclass↑n, 0<=n" and
"dependent" to mean "subclass↑n, 0<=n". In other places the
document uses "superclass" to mean the transitive closure and
"direct superclass" to mean the directly related classes, and
similarly for "subclass" and "direct subclass". We need to be
consistent about this. I believe the component/dependent
terminology is clearer, because it avoids using a single word to
mean two things, but other opinions are welcome.
I don't like the term component at all. It suggests a part hierarchy,
and for me any inheritance goes the wrong way; that is, components
inherit features from their container not the other way. For example, a
car door, a component of a car, is the same color as the car (usually).
Dependent is also a misleading word because of its usage wrt interface
dependencies where a view of an object is a dependent on the state of
the object itself.
I suggest instead consistently use the term direct super(sub)class, or
local super(sub)class versus the unmodified one to indicate the closure.
Or using the metaphor of the family, I suggest we use the terms parent
(child) class to refer to the immediate relationship, and ancestor
(descendant) for the generic relation. I prefer the first, which
requires the document to be made consistent.
danny
∂29-Dec-86 1830 Bobrow.pa@Xerox.COM Re: terminology confusion: Specifying Builtin classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Dec 86 18:30:38 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 29 DEC 86 17:27:54 PST
Date: 29 Dec 86 17:27 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: terminology confusion: Specifying Builtin classes
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sun, 28 Dec 86 18:55 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861229-172754-2578@Xerox>
Moon says:
The standard should not rule out any of these implementation
techniques; it should say that classes corresponding to types
defined in CLtL are permitted to be built-in classes, but not
required to be built-in classes. Thus portable programs cannot
make subclasses of such classes, but also cannot rely on an error
being signalled if they attempt to make a subclass. Taking
pathnames as an example again, ...
This is clearly correct (this means I agree) for pathnames. Is there
some set of these classes that must be built-in? What about
DOUBLE-FLOAT, etc. Is it the case for any built-in class that subtyping
is allowed ? Is CONS one of these? Ignoring in-line code for CAR and
CDR for the minute, could the user define a two way linked list as a
subclass of CONS? I am nervous about all that, and am tempted to say no
just from conservatism.
danny
∂29-Dec-86 1832 Bobrow.pa@Xerox.COM Re: terminology confusion
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Dec 86 18:31:43 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 29 DEC 86 18:10:51 PST
Date: 29 Dec 86 18:10 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: terminology confusion
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sun, 28 Dec 86 18:55 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861229-181051-2603@Xerox>
Moon says:
I propose we adopt as our first principle that "foo is a bar"
and (TYPEP FOO 'BAR) shall be equivalent.
This implies that to be consistent with CLtL that the name of the class
that is the super of all objects is T. Every foo in Common Lisp is a T,
that is (TYPE foo T) is always true. Hence, our choice of that name for
the common superclass of all items.
However, although the equivalence principle is a useful heuristic, it is
a mistake to think that all statements of the form "foo is a bar"
and (TYPEP FOO 'BAR) shall be equivalent.(e.g. "that is a badIdea")
However, I believe the following weaker statement should be a principle,
(TYPEP FOO 'BAR) should license the statement "foo is a bar"
The idea of shared behavior does not require an abstract class that all
inherit from. All classes must share is some minimal protocol, but not
necessarily by inheritance. The same is true for sequences. There need
be no class of named sequence.
Moon is sugesting that we always have an abstract class, and use a
prefix on a name to make a distinction. We chose to make this
distinction by using the short common name for the class the user would
most often need to read/write. Hence CLASS and OBJECT rather than
STANDARD-CLASS and STANDARD-OBJECT.
Since the concept of abstract classness need not be grasped by most
users, and the name of the shared abstract class ESSENTIAL-CLASS needs
to be known by only a few more, it does not seem worthwhile to start
from the strong version of the equivalence principle for these terms.
Not requiring a common superclass to express common properties is at the
heart of the recently expressed agreement to eliminate
STANDARD-TYPE-CLASS:
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU
Moon is right, BUILT-IN-CLASS and STANDARD-TYPE-CLASS ought to
denote different things by virtue of their English cognate
components, but we had intended that ``BUILT-IN-CLASS''
misleadingly refer to what we now define as ``STANDARD-TYPE-CLASS.''
In the absence of the unremembered examples, I would vote to
eliminate this class. Its only purpose would seem to be to enable
programmers to write code that would operate on objects
distinguished according to whether they were part of the
implementation of the object-oriented system or of the underlying
Common Lisp.
I agree with this agreement about eliminating STANDARD-TYPE-CLASS and
using BUILT-IN-CLASS to mean non-extensible (recognized primitively in
the underlying system).
danny
∂29-Dec-86 1830 Bobrow.pa@Xerox.COM Re: terminology confusion STRUCTURE-CLASS as a BUILT-IN-CLASS?
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Dec 86 18:29:47 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 29 DEC 86 17:18:20 PST
Date: 29 Dec 86 17:18 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: terminology confusion STRUCTURE-CLASS as a BUILT-IN-CLASS?
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sun, 28 Dec 86 18:55 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861229-171821-2566@Xerox>
Moon says:
Issue: is STRUCTURE-CLASS a subtype of BUILT-IN-CLASS? In
favor: structure classes have the properties of being instantiated
a special way and not being subclassable with DEFCLASS. Opposed:
the user can define new structure classes but only the Lisp
implementor can define new built-in classes, also structure classes
are subclassable, using the :include option to defstruct. My
answer is "no" but other opinions are welcome.
I agree. STRUCTURE-CLASS should not be a subtype of BUILT-IN-CLASS
since the user can make new ones using that metaclass.
danny
∂29-Dec-86 2111 RPG Terminology
To: common-lisp-object-system@SAIL.STANFORD.EDU
I believe we should distinguish immediate super/subclasses from
the transitive closure of those relationships. I don't believe
component/dependent are appropriate for the names of the transitive
closures.
For the moment I will call these relations superclass, subclass, superclass*,
and subclass*. Also, I will use these words as nouns to refer to objects that
bear the appropriate relationships to a given class.
A component is a constituent part or ingredient. A superclass* might not be
a constituent part of a class, because every aspect of it is shadowed.
A dependent is something that relies on or is subject to something else.
Again, a dependent might not depend on the superclass*, because everything
is shadowed.
``Component'' and ``dependent'' are not related words, and many people
who see the two together might not guess that one is the dual of the
other.
I think that we should use the terminology:
Term in this Message = New Term
superclass* = superclass
superclass = direct superclass
subclass* = subclass
subclass = direct subclass
Moon briefly raises the issue of the term ``lattice.'' The class lattice is
not simply a lattice: The local ordering of direct superclasses matters.
However, the class lattice is, then, a lattice with some additional properties.
A quick breeze through my MacLane and Birkoff reveals there is no existing
name for what we have. I believe we can still use the term ``lattice,'' but
the figures Moon mentions ought to be altered as he suggests.
-rpg-
∂29-Dec-86 2157 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: terminology confusion
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Dec 86 21:57:25 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 32400; Tue 30-Dec-86 00:56:33 EST
Date: Tue, 30 Dec 86 00:55 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: terminology confusion
To: Common-Lisp-Object-System@SU-AI.ARPA
In-Reply-To: <861229-181051-2603@Xerox>
Message-ID: <861230005542.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 29 Dec 86 18:10 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Moon says:
I propose we adopt as our first principle that "foo is a bar"
and (TYPEP FOO 'BAR) shall be equivalent.
....
However, although the equivalence principle is a useful heuristic, it is
a mistake to think that all statements of the form "foo is a bar"
and (TYPEP FOO 'BAR) shall be equivalent.(e.g. "that is a badIdea")
However, I believe the following weaker statement should be a principle,
(TYPEP FOO 'BAR) should license the statement "foo is a bar"
The idea of shared behavior does not require an abstract class that all
inherit from. All classes must share is some minimal protocol, but not
necessarily by inheritance. The same is true for sequences. There need
be no class of named sequence.
Right. I overlooked the unintentional implication that every is-a
word had to be a class (or at least a type).
If you'll allow me to rephrase the suggestion, the principle should
be ``If BAR is a valid type specifier, then "foo is a bar" and
(TYPEP FOO 'BAR) must be equivalent. "Foo is a quux" may be used
freely when QUUX is not a valid type specifier.''
Moon is sugesting that we always have an abstract class, and use a
prefix on a name to make a distinction. We chose to make this
distinction by using the short common name for the class the user would
most often need to read/write. Hence CLASS and OBJECT rather than
STANDARD-CLASS and STANDARD-OBJECT.
I'm not suggesting that we always have an abstract class. But I
definitely am saying that if the type-specifier CLASS is defined to be
something -different- from the English word class, confusion results in
the documentation. Thus, while using a short name for something the
user most often needs to read/write sounds like a good idea at first, I
don't think it is viable, because it makes the language too hard to
explain.
I actually do think that abstract classes for classes, methods, and
generic-functions will be useful, but that is an independent issue, and
I could be wrong without affecting the argument that CLASS is a poor
name for the standard metaclass.
∂29-Dec-86 2207 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: terminology confusion: Specifying Builtin classes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Dec 86 22:07:10 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 32405; Tue 30-Dec-86 01:06:17 EST
Date: Tue, 30 Dec 86 01:05 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: terminology confusion: Specifying Builtin classes
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <861229-172754-2578@Xerox>
Message-ID: <861230010529.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 29 Dec 86 17:27 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Moon says:
The standard should not rule out any of these implementation
techniques; it should say that classes corresponding to types
defined in CLtL are permitted to be built-in classes, but not
required to be built-in classes. Thus portable programs cannot
make subclasses of such classes, but also cannot rely on an error
being signalled if they attempt to make a subclass. Taking
pathnames as an example again, ...
This is clearly correct (this means I agree) for pathnames. Is there
some set of these classes that must be built-in?
The only discussion of this that I could find in CLtL is the section
"Overlap, Inclusion, and Disjointness of Types" (pp.33-5). It does not
say that types created by defstruct are disjoint from any types besides
other types created by defstruct. Thus I think it allows any type, even
fixnum, to be implemented in a non-built-in fashion. Leaving maximum
freedom to the implementor in places where program portability is not
seriously affected is usually the Common Lisp philosophy.
What about
DOUBLE-FLOAT, etc. Is it the case for any built-in class that subtyping
is allowed ? Is CONS one of these? Ignoring in-line code for CAR and
CDR for the minute, could the user define a two way linked list as a
subclass of CONS? I am nervous about all that, and am tempted to say no
just from conservatism.
I don't think subtyping (user-defined creation of new subtypes not
provided by the implementation) is allowed for any built-in class;
that's what it means to be built-in, isn't it? An implementation that
allowed users to define new subclasses of CONS (I know of two, but they
are not Common Lisps, and there could be others) would not consider CONS
a built-in class. Consider that Lisp done by those two guys at CMU in
which no types are built-in (they had a paper at OOPSLA). It's actually
pretty reasonable to implement DOUBLE-FLOAT as a standard class.
The tricky thing is that no class is guaranteed to be built-in in every
implementation, but all the CLtL classes are allowed to be built-in
in some implementations, which means that portable programs must
not do things to them that aren't allowed for built-in classes. My
anecdote about pathnames was an argument that it is infeasible to
get around this imprecision of the Common-Lisp-plus-objects language.
∂29-Dec-86 2220 Masinter.pa@Xerox.COM Comments on various comments
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Dec 86 22:19:32 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 29 DEC 86 18:33:48 PST
Date: 29 Dec 86 18:33 PST
From: Masinter.pa@Xerox.COM
Subject: Comments on various comments
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sun, 28 Dec 86 17:18 EST
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861229-183348-2667@Xerox>
I'm sorry this message is too long, since I'm mainly agreeing with Moon,
although there are a few places that I disagree or have
counter-proposals.
Re: DECLARE option to DEFGENERIC(-OPTIONS
I observe that the discussion on type declarations inside
defgeneric(-options) seems to lack any correlation with Object-System
concepts -- this seems like an issue for the "types and declarations"
committee, and perhaps *any* form of type declarations for generic
functions should be left out of the standard until there is some better
clarification of function-type specifications, which seem like they are
in need of repair.
Re: make-method issue
I agree with Dave's proposal for removing make-method from the standard,
and specifying the functional interface for creating methods by
make-instance of a method-class; it would simplify the document, and
encourage a standard practice of using make-instance where appropriate,
rather than individual "make-" constructors.
Re: terminology confusion
I agree that it is clarifying and an improvement to proclaim that
everything which "is a class" also satisfies (TYPEP x 'CLASS). The issue
is whether the "standard" kind of class can be called CLASS and have all
"non-standard" classes shadow the behavior in whatever ways they want,
or whether it is necessary to reify the default behavior. Looking to
the rest of Common Lisp for analogies gives STRING and STANDARD-STRING
(which has a subtly different meaning for "standard" than Dave proposes)
but ARRAY with no STANDARD-ARRAY, VECTOR with no STANDARD-VECTOR.
Would the language suffer if (CLASS-OF (MAKE-INSTANCE 'CLASS)) were left
unspecfied except that the result was a subclass of CLASS? I.e., if
there were no STANDARD-CLASS, STANDARD-METHOD, STANDARD-INSTANCE?
In resonse to Dave's Issue: is STRUCTURE-CLASS a subtype of
BUILT-IN-CLASS?
Reply: we haven't defined what BUILT-IN-CLASS is, other than to say a
built-in class can have no subclasses. In this regard, structure classes
differ since they at least offer single inheritance, so I would answer
No. I think this just points to the poverty of the notion of "built in
class" rather than a serious design issue.
To turn this into a proposal, I would propose removing BUILT-IN-CLASS as
a language construct and instead explain it as a concept -- that is,
some of the types in CLtL correspond to built-in classes which cannot be
subclassed, e.g., FIXNUM. Some types cannot reliably be subclassed,
although future implementations are encouraged to move toward such an
implementation, e.g., PATHNAME, NUMBER.
In response to the terminology issue of component/dependent vs
subclass/superclass:
using subclass for transitive closure of direct subclass and superclass
for transitive closure of direct superclass seems in my memory to be
more prevalent at least in the Object Oriented Programming literature.
That it uses a single word to mean two things is not so serious since
there is a direct relationship (as opposed to just "a relationship")
between the two things. To use the mathematical analogy to its fullest,
"A is a subclass of B" should be allowed when A = B, and "A is a proper
subclass of B" be used to describe the situation where A /= B.
∂29-Dec-86 2226 RPG Re: Terminology
∂29-Dec-86 2220 masinter.PA@Xerox.COM Re: Terminology
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Dec 86 22:19:41 PST
Received: from Chardonnay.ms by ArpaGateway.ms ; 29 DEC 86 21:53:24 PST
From: masinter.PA@Xerox.COM
Date: 29 Dec 86 21:51:12 PST
Subject: Re: Terminology
In-reply-to: RPG@SAIL.STANFORD.EDU's message of 29 Dec 86 21:11 PST
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861229-215324-2730@Xerox>
and subclass+ = proper subclass, superclass+ = proper superclass?
Masinter.pa@xerox/su
Terminology
You could define things this way. I feel that `component' and `dependent'
introduce two extra terms for no good reason, and these terms are not
very good. I'm open to suggestions. What do you think are good terms?
Normally people will refer to superclasses, not really caring whether they
are direct, so that should be the common case.
-rpg-
∂30-Dec-86 1033 Bobrow.pa@Xerox.COM Re: Comments on various comments
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Dec 86 10:33:27 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 DEC 86 10:06:14 PST
Date: 30 Dec 86 10:06 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Comments on various comments
In-reply-to: Masinter.pa's message of 29 Dec 86 18:33 PST
To: Masinter.pa@Xerox.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861230-100614-2921@Xerox>
Larry says:
In resonse to Dave's Issue: is STRUCTURE-CLASS a subtype of
BUILT-IN-CLASS? Reply: we haven't defined what BUILT-IN-CLASS is,
other than to say a built-in class can have no subclasses. In this
regard, structure classes differ since they at least offer single
inheritance, so I would answer No. I think this just points to the
poverty of the notion of "built in class" rather than a serious
design issue. To turn this into a proposal, I would propose
removing BUILT-IN-CLASS as a language construct and instead explain
it as a concept -- that is, some of the types in CLtL correspond to
built-in classes which cannot be subclassed, e.g., FIXNUM. Some
types cannot reliably be subclassed, although future
implementations are encouraged to move toward such an
implementation, e.g., PATHNAME, NUMBER.
I disagree here, because one wants to support the behavior within an
implementation of disallowing subclassing. Having a metaclass
BUILT-IN-CLASS both supports this in a natural way, and allows an easy
user test of non-extensibility.
I think previous arguments against making STRUCTURE-CLASS a subtype of
BUILT-IN-CLASS are convincing (i.e. Moon and I agree anyway).
Larry says:
The issue is whether the "standard" kind of class can be called
CLASS and have all "non-standard" classes shadow the behavior in
whatever ways they want, or whether it is necessary to reify the
default behavior.
The reason we have ESSENTIAL-CLASS and CLASS is that there is some
behavior that is shared by BUILT-IN-CLASS and CLASS, but a lot of
behavior of CLASS (e.g. finding the slots) that BUILT-IN-CLASS does not
have. Otherwise this suggestion of shadowing to make CLASS and "class"
be the same would work.
Moon says:
But I definitely am saying that if the type-specifier CLASS is
defined to be something -different- from the English word class,
confusion results in the documentation. Thus, while using a short
name for something the user most often needs to read/write sounds
like a good idea at first, I don't think it is viable, because it
makes the language too hard to explain.
I don't think so. I think OBJECT and object are good counter examples.
The English usage allows "object" to refer to any thing. We choose to
use OBJECT in a technical sense, limiting its scope. It means we have
to use another term when we want to refer to any Common Lisp item or
type. Similarly, I am suggesting we use "class" to refer to the general
concept of describing items, and CLASS as the name of the class that
describes OBJECT's. This is done in mathematics all the time e.g. sets
are any collections of objects, but mathematically SETs can not be
defined in terms of arbitrary predicates (e.g. those who do not shave
themselves).
danny
∂30-Dec-86 1033 Bobrow.pa@Xerox.COM Re: terminology confusion
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Dec 86 10:33:36 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 DEC 86 10:09:26 PST
Date: 30 Dec 86 10:09 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: terminology confusion
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 30 Dec 86 00:55 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861230-100926-2923@Xerox>
I actually do think that abstract classes for classes, methods,
and generic-functions will be useful, but that is an independent
issue, and I could be wrong without affecting the argument that
CLASS is a poor name for the standard metaclass.
I think my previous message argued just the opposite. In PCL we have
ESSENTIAL-CLASS, ESSENTIAL-GENERIC-FUNCTION, ESSENTIAL-METHOD as
abstract classes, and use the shorter names to refer to the more useful
fuller definitons. Perhaps if we simply defined the terms
essential-class etc we could use those in English sentences and get the
explanatory power we want without sacrificing the short names.
danny
∂30-Dec-86 1035 RPG Re: Terminology
∂30-Dec-86 0059 masinter.pa@Xerox.COM Re: Terminology
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Dec 86 00:59:09 PST
Received: from Chardonnay.ms by ArpaGateway.ms ; 29 DEC 86 22:59:52 PST
From: masinter.pa@Xerox.COM
Date: 29 Dec 86 22:57:40 PST
Subject: Re: Terminology
In-reply-to: Your message of 29 Dec 86 22:25 PST
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
cc: Masinter.pa@Xerox.COM
Message-ID: <861229-225952-2775@Xerox>
?? I agree with you, I dislike compoenent and dependent. I like your
redefinitions. I just thought that you left one term out.
I especially think it is important if we are ever going to add a
capability of "splicing" classes, e.g.
"add a new abstract class called groupoid between number and T" and
then define some methods on groupoids which work on numbers and other
instances of (subclasses of) groupoids.
Maybe this is
(deftype groupoid () '(or number sub-groupoid))
and allowing "or" types in methods?
∂30-Dec-86 1034 Bobrow.pa@Xerox.COM Re: Terminology
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Dec 86 10:34:01 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 DEC 86 10:15:38 PST
Date: 30 Dec 86 10:15 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Terminology
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 29 Dec 86
21:11 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861230-101538-2927@Xerox>
Term in this Message = New Term
superclass* = superclass
superclass = direct superclass
subclass* = subclass
subclass = direct subclass
I agree that it would be good to consistently use the terms in column New Term.
danny
∂30-Dec-86 1034 Bobrow.pa@Xerox.COM Re: Issues in Concepts chapter
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Dec 86 10:34:12 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 DEC 86 10:20:35 PST
Date: 30 Dec 86 10:20 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Issues in Concepts chapter
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 29 Dec 86 15:16 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861230-102035-2931@Xerox>
Initialization protocol is still to be defined.
Gregor sent out a proposal. Any comments.
danny
∂30-Dec-86 1037 RPG Re: Terminology
∂30-Dec-86 0059 masinter.PA@Xerox.COM Re: Terminology
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Dec 86 00:59:16 PST
Received: from Chardonnay.ms by ArpaGateway.ms ; 30 DEC 86 00:06:39 PST
From: masinter.PA@Xerox.COM
Date: 30 Dec 86 0:04:26 PST
Subject: Re: Terminology
In-reply-to: Your message of 29-Dec-86 22:57:40 PST
To: masinter.PA@Xerox.COM
cc: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861230-000639-2782@Xerox>
My message was too brief. The referent of "it" in "I especially like it
if..." is "using 'subclass' to mean the transitive closure rather than
the direct subclass". Its Its a better choice of terminology because it
corresponds better to the mathematical terms which we are borrowing, and
also because the short word is more frequently useful.
∂30-Dec-86 1036 RPG Re: Terminology
∂30-Dec-86 0059 masinter.PA@Xerox.COM Re: Terminology
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Dec 86 00:59:16 PST
Received: from Chardonnay.ms by ArpaGateway.ms ; 30 DEC 86 00:06:39 PST
From: masinter.PA@Xerox.COM
Date: 30 Dec 86 0:04:26 PST
Subject: Re: Terminology
In-reply-to: Your message of 29-Dec-86 22:57:40 PST
To: masinter.PA@Xerox.COM
cc: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861230-000639-2782@Xerox>
My message was too brief. The referent of "it" in "I especially like it
if..." is "using 'subclass' to mean the transitive closure rather than
the direct subclass". Its Its a better choice of terminology because it
corresponds better to the mathematical terms which we are borrowing, and
also because the short word is more frequently useful.
∂30-Dec-86 1033 Bobrow.pa@Xerox.COM Re: terminology confusion: Specifying Builtin classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Dec 86 10:33:43 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 DEC 86 10:11:21 PST
Date: 30 Dec 86 10:11 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: terminology confusion: Specifying Builtin classes
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 30 Dec 86 01:05 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861230-101121-2926@Xerox>
Moon says:
An implementation that allowed users to define new subclasses of
CONS (I know of two, but they are not Common Lisps, and there could
be others) would not consider CONS a built-in class. Consider that
Lisp done by those two guys at CMU in which no types are built-in
(they had a paper at OOPSLA). It's actually pretty reasonable to
implement DOUBLE-FLOAT as a standard class.
The tricky thing is that no class is guaranteed to be built-in
in every implementation, but all the CLtL classes are allowed to be
built-in in some implementations, which means that portable
programs must not do things to them that aren't allowed for
built-in classes. My anecdote about pathnames was an argument that
it is infeasible to get around this imprecision of the
Common-Lisp-plus-objects language.
I take this to mean that we use BUILT-IN-CLASS as a signal within an
implementation that no subclassing is allowed, but that we do not
specify any classes that MUST be built-in. I agree.
danny
∂30-Dec-86 1126 RPG Terminology (sort of): A New Question
To: common-lisp-object-system@SAIL.STANFORD.EDU
As you probably know, I am going through the CONCEPTS part of the
document and trying to regularize the terminology. I will make no
major changes to terminology without first asking this list.
In the discussion of DEFCLASS slots, there is mention of the default
value for a slot. Because a form can appear there, and the form is
evaluated to yield a value, I propose to discussion the default
value form rather than the default value. Agreed?
-rpg-
∂30-Dec-86 1139 Moon@STONY-BROOK.SCRC.Symbolics.COM Terminology: default value form
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Dec 86 11:38:57 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 32784; Tue 30-Dec-86 14:37:37 EST
Date: Tue, 30 Dec 86 14:36 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Terminology: default value form
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 30 Dec 86 14:26 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <861230143647.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 30 Dec 86 1126 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
In the discussion of DEFCLASS slots, there is mention of the default
value for a slot. Because a form can appear there, and the form is
evaluated to yield a value, I propose to discussion the default
value form rather than the default value. Agreed?
Yes, "default value form" sounds right to me.
∂30-Dec-86 1215 Masinter.pa@Xerox.COM Re: Terminology
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Dec 86 12:14:57 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 DEC 86 10:56:02 PST
Date: 30 Dec 86 10:55 PST
From: Masinter.pa@Xerox.COM
Subject: Re: Terminology
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <861230-105602-300@Xerox>
Term in this Message = New Term
superclass* = superclass
superclass = direct superclass
subclass* = subclass
subclass = direct subclass
I agree with the New Term naming. I would like to add
superclass+ = proper superclass
subclass+ = proper subclass
An alternative (which I am not as fond of) would be
superclass+ = superclass
superclass = direct superclass
superclass* = same or superclass
etc.
∂30-Dec-86 1214 Masinter.pa@Xerox.COM Re: Comments on various comments
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Dec 86 12:14:45 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 DEC 86 10:52:42 PST
Date: 30 Dec 86 10:52 PST
From: Masinter.pa@Xerox.COM
Subject: Re: Comments on various comments
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 30 Dec 86 10:06 PST
To: Bobrow.pa@Xerox.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861230-105242-300@Xerox>
Danny says: "I disagree here, because one wants to support the behavior
within an implementation of disallowing subclassing."
I agree, one wants to support the behavior within an implementation of
disallowing subclassing. However, the BUILT-IN-CLASS mechanism doesn't
support that behavior very well. It seems unnatural to promote the use
of BUILT-IN-CLASS as a superclass to disallow subclassing. E.g., would
you have (defclass frob-class (built-in-class standard-class))?
I was having trouble thinking up of any other examples of where one
would use BUILT-IN-CLASS in a program.
(TYPEP (CLASS-OF x) 'BUILT-IN-CLASS) seems like a poor way to test
whether subclassing is available, as the inheritance behavior seems to
be more complex than just "allowed" or "disallowed" (e.g.,
structure-class supports only single inheritance, etc.)
Perhaps one might want to write methods on BUILT-IN-CLASS, e.g.
(defmethod make-instance ((x built-in-class))
(error "Cannot make a ~S with make-instance." (class-name x))
but that seems like the only example that makes much sense.
- - - - - - -
Danny says: "The reason we have ESSENTIAL-CLASS and CLASS is that there
is some behavior that is shared by BUILT-IN-CLASS and CLASS, but a lot
of behavior of CLASS (e.g. finding the slots) that BUILT-IN-CLASS does
not have. Otherwise this suggestion of shadowing to make CLASS and
"class" be the same would work."
Reply: most of that behavior is interesting and could easily be shadowed
or given an interpretation for built-in-class, e.g., finding the slots
might make sense for some built-in classes (CONS comes to mind).
Summary:
The issue is over the class names for the top of the class hierarchy for
classes, generic functions and methods. The proposals are
a) (current document) top of heirarchy is ESSENTIAL-CLASS,
ESSENTIAL-GENERIC-FUNCTION, ESSENTIAL-METHOD, with the "default" ones
named CLASS, GENERIC-FUNCTION, METHOD
b) (moon) top of hierarchy is CLASS, GENERIC-FUNCTION, METHOD, with the
default ones named STANDARD-CLASS, STANDARD-GENERIC-FUNCTION,
STANDARD-METHOD
c) (masinter) top of hierarchy is CLASS, GENERIC-FUNCTION, METHOD, with
the names of the default ones unspecified, some implementations can in
fact use CLASS, GENERIC-FUNCTION, METHOD and shadow any unwanted
behavior in the subclasses.
Critera:
1) are the most frequently used constructs given the short names?
2) are the programming constructs consistent with the English
descriptions?
3) does the design consistent with most reasonable implementations &
extensions
4) are there no evident design-flaws, e.g., cases that don't work.
Are there other proposals? Other critera?
∂30-Dec-86 1236 RPG Clarfication on ``superclass''
To: common-lisp-object-system@SAIL.STANFORD.EDU
Would you prefer to use the term ``proper superclass''
or would you prefer to define that a class is not a superclass
of itself?
-rpg-
∂30-Dec-86 1332 Bobrow.pa@Xerox.COM Re: Terminology: default value form
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Dec 86 13:32:12 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 DEC 86 13:06:33 PST
Date: 30 Dec 86 13:06 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Terminology: default value form
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 30 Dec 86 14:36 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861230-130633-1091@Xerox>
Date: 30 Dec 86 1126 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
In the discussion of DEFCLASS slots, there is mention of the default
value for a slot. Because a form can appear there, and the form is
evaluated to yield a value, I propose to discussion the default
value form rather than the default value. Agreed?
Moon says:
Yes, "default value form" sounds right to me.
Didn't we agree that inital value form would be better. That is, this
is a form evaluated to provide an initial value, rather than one that is
used for a default value (as in Loops) that one fetches when finding an
uninitialized slot in an object.
Hence I would propose we call it "initial value form" and it is
abbvreviated in the syntax as initform (and has keyword in defclass as
:initform)
danny
∂30-Dec-86 1332 Bobrow.pa@Xerox.COM Re: Clarfication on ``superclass''
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Dec 86 13:32:17 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 DEC 86 13:13:51 PST
Date: 30 Dec 86 13:13 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Clarfication on ``superclass''
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 30 Dec 86
12:36 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <861230-131351-1097@Xerox>
Would you prefer to use the term ``proper superclass'' or would
you prefer to define that a class is not a superclass of itself?
-rpg-
I prefer to say that a class is not a superclass of itself. The only
use of proper might come up in testing, where we use the terminology of
types. (SUBTYPEP 'object 'object) and (SUBTYPEP 'class 'object) are
both true. We need a function that will take two classes and return T if
the first is equal to or a subclass of the second. Should this be named
SUBCLASSP? IS-A?
danny
∂30-Dec-86 1620 Dussud%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Terminology (sort of): A New Question
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 30 Dec 86 16:20:46 PST
Received: from ti-csl by csnet-relay.csnet id ab01647; 30 Dec 86 18:34 EST
Received: from Jenner (jenner.ARPA) by tilde id AA09489; Tue, 30 Dec 86 16:18:10 cst
To: Dick Gabriel <RPG@SU-AI.ARPA>
Cc: common-lisp-object-system@SU-AI.ARPA
Subject: Re: Terminology (sort of): A New Question
Date: 30-Dec-86 15:19:54
From: Dussud%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <Dussud.2745350392@Jenner>
In the discussion of DEFCLASS slots, there is mention of the default
value for a slot. Because a form can appear there, and the form is
evaluated to yield a value, I propose to discussion the default
value form rather than the default value. Agreed?
OK!
Patrick.
∂30-Dec-86 2149 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Terminology: default value form
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Dec 86 21:48:57 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 33142; Wed 31-Dec-86 00:48:07 EST
Date: Wed, 31 Dec 86 00:47 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Terminology: default value form
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <861230-130633-1091@Xerox>
Message-ID: <861231004721.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 30 Dec 86 13:06 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Date: 30 Dec 86 1126 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
In the discussion of DEFCLASS slots, there is mention of the default
value for a slot. Because a form can appear there, and the form is
evaluated to yield a value, I propose to discussion the default
value form rather than the default value. Agreed?
Moon says:
Yes, "default value form" sounds right to me.
Didn't we agree that inital value form would be better. That is, this
is a form evaluated to provide an initial value, rather than one that is
used for a default value (as in Loops) that one fetches when finding an
uninitialized slot in an object.
Hence I would propose we call it "initial value form" and it is
abbvreviated in the syntax as initform (and has keyword in defclass as
:initform)
"initial value form" rather than "default value form" is fine.
I find the abbreviation repulsive, though.
∂30-Dec-86 2152 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Terminology: default value form
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Dec 86 21:51:58 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 33147; Wed 31-Dec-86 00:51:09 EST
Date: Wed, 31 Dec 86 00:50 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Terminology: default value form
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <861230-130633-1091@Xerox>
Supersedes: <861231004721.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <861231005024.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
[Please disregard the earlier version of this message sent accidentally.]
Date: 30 Dec 86 13:06 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Date: 30 Dec 86 1126 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
In the discussion of DEFCLASS slots, there is mention of the default
value for a slot. Because a form can appear there, and the form is
evaluated to yield a value, I propose to discussion the default
value form rather than the default value. Agreed?
Moon says:
Yes, "default value form" sounds right to me.
Didn't we agree that inital value form would be better. That is, this
is a form evaluated to provide an initial value, rather than one that is
used for a default value (as in Loops) that one fetches when finding an
uninitialized slot in an object.
Hence I would propose we call it "initial value form" and it is
abbvreviated in the syntax as initform (and has keyword in defclass as
:initform)
"initial value form" rather than "default value form" is fine, although
I don't see why users would expect this system to behave like LOOPS. It
doesn't seem to have much resemblance to LOOPS. One could argue that
the word "default" here is justified because this form only provides the
initial value if another initial value is not specified by the caller
of MAKE-INSTANCE. Thus it is the DEFAULT initial value form.
My conclusion is that either "initial value form" or "default value
form" is acceptable.
I find the abbreviation "initform" repulsive, though.
∂30-Dec-86 2204 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Comments on various comments
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Dec 86 22:04:40 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 33152; Wed 31-Dec-86 01:03:49 EST
Date: Wed, 31 Dec 86 01:03 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Comments on various comments
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <861230-100614-2921@Xerox>
Message-ID: <861231010304.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 30 Dec 86 10:06 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
[other issues deleted for now]
Moon says:
But I definitely am saying that if the type-specifier CLASS is
defined to be something -different- from the English word class,
confusion results in the documentation. Thus, while using a short
name for something the user most often needs to read/write sounds
like a good idea at first, I don't think it is viable, because it
makes the language too hard to explain.
I don't think so. I think OBJECT and object are good counter examples.
The English usage allows "object" to refer to any thing. We choose to
use OBJECT in a technical sense, limiting its scope. It means we have
to use another term when we want to refer to any Common Lisp item or
type.
Doesn't that prove my point? The use of the term OBJECT to mean something
different from object is highly confusing. (For those who didn't beat
their way through the confusion with a machete, in the 30 Oct version of
the Concepts chapter, but not the 23 Dec version, OBJECT is defined to be
the class of the subset of objects whose metaclass is CLASS, whereas object
is used (but not explicitly defined) to mean any Lisp value).
Similarly, I am suggesting we use "class" to refer to the general
concept of describing items, and CLASS as the name of the class that
describes OBJECT's. This is done in mathematics all the time e.g. sets
are any collections of objects, but mathematically SETs can not be
defined in terms of arbitrary predicates (e.g. those who do not shave
themselves).
Weren't mathematicians confused for centuries by this?
∂31-Dec-86 1514 RPG STANDARD-TYPE-CLASS
To: common-lisp-object-system@SAIL.STANFORD.EDU
I want to settle this terminological issue soon. Here is a review of the
situation.
There are two terms under discussion: BUILT-IN-CLASS and
STANDARD-TYPE-CLASS. BUILT-IN-CLASS ought, by virtue of English
resemblances, to denote a class whose instances are classes whose
instances are entities that the implementors of a particular Common Lisp
have decided to fundamentally represent. STANDARD-TYPE-CLASS ought to
denote a class whose instances are classes whose instances are entities
explained on page 43 of CLtL (roughly speaking).
The class BUILT-IN-CLASS would be useful for people who are writing
programs that reason about the underlying implementation of the Common
Lisp, for example. The class STANDARD-TYPE-CLASS would be useful for
people who are writing programs that are reasoning about the objects that
are CLtL objects rather than objects that are instances of classes defined
by some other programmer, for example.
One would expect that every Common Lisp would behave the same with respect
to STANDARD-TYPE-CLASS and that every Common Lisp would, generally, behave
differently with respect to BUILT-IN-CLASS.
In early mail and discussions about classes generally referring to one or
both of these classes, the term BUILT-IN-CLASS was used uniformly. Danny,
Gregor, and I decided that most people who see the term BUILT-IN-CLASS
would think that it referred to what we now call STANDARD-TYPE-CLASS, so
we changed the name from BUILT-IN-CLASS to STANDARD-TYPE-CLASS. We
thought both that people would not want to write code that distinguished
entities fundamental to the underlying Common Lisp and that people ought
to be disallowed from writing such code even if they thought of doing it.
The point of some of these metaclasses is to create objects in the
metaclass world that help people write programs that understand how the
world of normal classes and instances is carved up. They act as ideas in a
program-accessible Plato's heaven.
In an earlier message I argued that we might as well eliminate
STANDARD-TYPE-CLASS and BUILT-IN-CLASS. I've changed my mind.
I think that some structure in the metaworld to reflect structure in the
Lisp world is useful and that some people will want to write programs to
reason about that structure. Moreover, I don't think we should prevent
people from doing that, and I think we should provide that structure
because we are likely to get it right and other people are not likely to
get it right if they try to provide it for themselves.
So, the class we now call STANDARD-TYPE-CLASS ought to be provided,
possibly with a different name. The class we call BUILT-IN-CLASS is
different, and possibly we should provide it as well. If we provide both,
with these two names, the contrast that the existence of both names
creates will help disambiguate them, eliminating problems with
name choice.
-rpg-
∂31-Dec-86 1529 Bobrow.pa@Xerox.COM Re: make-method issue
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 31 Dec 86 15:27:25 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 31 DEC 86 10:25:04 PST
Date: 31 Dec 86 10:24 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: make-method issue
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sun, 28 Dec 86 17:18 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861231-102504-1330@Xerox>
Moon says:
If people are supposed to use make-instance, rather than
make-method, to make methods, then we should document the arguments
to make-instance to be used for that purpose. Having done that,
there doesn't seem to be any reason to retain make-method.
I prefer eliminating make-method. Unless Gregor (who is away till next
week) has a good argument, I prefer to skip the unnecessary "functional"
interface. After all, calling the function make-instance with specifies
arguments is just as "functional".
danny
∂31-Dec-86 1529 Bobrow.pa@Xerox.COM Re: :allocation slot-option issues
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 31 Dec 86 15:27:31 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 31 DEC 86 10:26:01 PST
Date: 31 Dec 86 10:16 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: :allocation slot-option issues
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 29 Dec 86 00:11 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861231-102601-1332@Xerox>
(1) The document currently says
If the allocation type is :class, storage for the slot is
allocated in the class object created by the defclass form. The
value of the slot is shared by all instances of the class. Any
subclass of this class will share this single slot unless the
defclass form for that subclass specifies a slot of the same
name.
This is okay, but points up an inconsistency between
instance-variables and class-variables. Repeating the slot
declaration of an instance variable does not create two separate
slots, but repeating the slot declaration of a class variable does.
I'm sure Alan Snyder would say that we should change instance
variables to do the same as class variables, but I prefer to wonder
if this indicates that something about class variables is broken.
This is not the same as my model. Repeating the slot declaration of a
class variable does not create two separate slots accessible from any
particular instance. It creates a new one that overrides the one that
would be inherited. This is the same model as instance variables as far
as I am concerned.
I like to think (talk about) the access scope of class and instance
variables (whoops I should say slots):
1) There is one variable by any name accessible from an instance.
2) It is the one nearest in scope. If there is an instance variable
by that name, then it is the one, else it is the one in the class of the
instance or the most specific superclass of that class. This is the
same kind of nesting one gets in instantiation of function calls with
lexical scoping. If there is a local variable in the function, the
local value in the activation is accessed, else the nested scopes
containing the function definition are searched. I think the analogy
with inherited classes is very strong. Another analogy is to think of
classes as providing descriptions of sets, and subclasses describing
instances of subsets. Then the class variables are shared abong all
instances of the set.
Several months ago I remember we discussed splitting
:allocation :class into :allocation :per-class and :allocation
:shared (or some names like that) to address this problem.
:per-class slots get a new copy for each dependent subclass,
whereas :shared slots are shared among all dependent subclasses,
even if the slot declaration is repeated. I think either the
discussion was before this group got started or else it quickly
dropped out of sight; I can't find it in any mail archives. Can we
open this issue and discuss the pros and cons of making this change?
Neither of :per-class or :shared as you describe it has the semantics I
mentioned. Perhaps it would be useful to have an option
:this-direct-class-only (meaning the class slot was accessible only to
instances of this direct class), but I find that confusing with respect
to the inheritance story.
danny
∂31-Dec-86 1529 Bobrow.pa@Xerox.COM Re: :allocation slot-option issues
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 31 Dec 86 15:27:17 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 31 DEC 86 10:18:17 PST
Date: 31 Dec 86 10:16 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: :allocation slot-option issues
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 29 Dec 86 00:11 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <861231-101817-1327@Xerox>
(1) The document currently says
If the allocation type is :class, storage for the slot is
allocated in the class object created by the defclass form. The
value of the slot is shared by all instances of the class. Any
subclass of this class will share this single slot unless the
defclass form for that subclass specifies a slot of the same
name.
This is okay, but points up an inconsistency between
instance-variables and class-variables. Repeating the slot
declaration of an instance variable does not create two separate
slots, but repeating the slot declaration of a class variable does.
I'm sure Alan Snyder would say that we should change instance
variables to do the same as class variables, but I prefer to wonder
if this indicates that something about class variables is broken.
This is not the same as my model. Repeating the slot declaration of a
class variable does not create two separate slots accessible from any
particular instance. It creates a new one that overrides the one that
would be inherited. This is the same model as instance variables as far
as I am concerned.
I like to think (talk about) the access scope of class and instance
variables (whoops I should say slots):
1) There is one variable by any name accessible from an instance.
2) It is the one nearest in scope. If there is an instance variable
by that name, then it is the one, else it is the one in the class of the
instance or the most specific superclass of that class. This is the
same kind of nesting one gets in instantiation of function calls with
lexical scoping. If there is a local variable in the function, the
local value in the activation is accessed, else the nested scopes
containing the function definition are searched. I think the analogy
with inherited classes is very strong. Another analogy is to think of
classes as providing descriptions of sets, and subclasses describing
instances of subsets. Then the class variables are shared abong all
instances of the set.
Several months ago I remember we discussed splitting
:allocation :class into :allocation :per-class and :allocation
:shared (or some names like that) to address this problem.
:per-class slots get a new copy for each dependent subclass,
whereas :shared slots are shared among all dependent subclasses,
even if the slot declaration is repeated. I think either the
discussion was before this group got started or else it quickly
dropped out of sight; I can't find it in any mail archives. Can we
open this issue and discuss the pros and cons of making this change?
Neither of :per-class or :shared as you describe it has the semantics I
mentioned. Perhaps it would be useful to have an option
:this-direct-class-only (meaning the class slot was accessible only to
instances of this direct class), but I find that confusing with respect
to the inheritance story.
danny
∂31-Dec-86 1726 Bobrow.pa@Xerox.COM Method Combination Proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 31 Dec 86 17:26:10 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 31 DEC 86 17:25:03 PST
Date: 31 Dec 86 17:24 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Method Combination Proposal
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
cc: Bobrow.pa@Xerox.COM
Message-ID: <861231-172503-1727@Xerox>
The following is my current best proposal for method combination. It
was constructed by editing the expalnatory text originally sent by Moon.
Date: Wed, 15 Oct 86 23:39 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Method combination -- writeup for revised syntax
It contains my latest beliefs about the "right" way of doing this based
on our net conversations. It should contain no surprises. There is
only one method combination form, it is simple, but it allows
connections to the environment Moon said were desirable.
>>>COMPUTING EFFECTIVE METHODS
When a generic function is called with particular arguments, it must
decide
what code to run. We call the code it runs the "effective method" for
those arguments.
Methods are defined with the form:
defmethod generic-function-name <qualifier>* specialized-lambda-list ...
We call a method with zero qualifiers an "unqualified" method (and
conversely, one with one or more qualifiers a qualified method).
The specialized-lambda-list specifies the specialized parameters of the
method. A specialized parameter is a required argument limited to a
given type. The method will only be invoked if the argument is a
(sub)type of that given type.
We will describe the definition of effective method in stages. First
we will consider standard generic functions, with only unqualified
methods. Then we will consider generic functions that have a special
method-combination mechanism. Steps 1 and 2
1. Select the set of applicable methods.
The set of applicable methods consists of all methods for that generic
function whose specialized parameters match their corresponding
arguments. An argument x matches a specialized parameter if:
a) the parameter is specialized using a class name C, and
(typep x C) is true
b) the parameter is not specialized --
this is equivalent to being specialized with class T.
c) the parameter is specialized with (QUOTE v) and
(EQL x v) is true.
2. Sort the applicable methods into a precedence order, with most
specific method first.
To compare the precedence of two methods, examine their parameter
specializers in order. The default examination order is from left to
right, but may be otherwise specified as a parameter of
DEFGENERIC-OPTIONS.
An unspecialized parameter has a default parameter specializer of T. The
first pair of parameter specializers that are not equal determine the
precedence. Method X is more specific than method Y if method X's
parameter specializer is earlier than method Y's parameter specializer
in the class precedence list of the class of the argument. Since both
methods are applicable, it is guaranteed that the parameter specializers
for this argument are present in the class precedence list of the class
of the argument.
T is implied at the very end of each class precedence list, so it is
less
specific than any other class. (QUOTE individual) is more specific than
any class.
The resulting list of available methods is sorted with the most specific
method first and the least specific method at the end.
3. Considering a standard generic function with only unqualified
methods, the effective method is the most specific method. That method
can, in its body, call the next most specific method using the form
(CALL-NEXT-METHOD).
In general though, the effective method will be some combination of the
set of applicable methods, including qualified methods. The effective
method is constructed has as its body a form computed by a method on the
generic function. This form contains calls to some or all of the
methods, defines the value(s) to be returned by the generic function,
and optionally makes some of the methods reachable via CALL-NEXT-METHOD,
rather than calling them directly.
The mechanism for building the form is specified in part by the method
combination type that can be specified in the DEFGENERIC-OPTIONS form
for the
generic function. The meaning of the qualifiers of a method is defined
entirely by step 3 of the above procedure. These qualifiers give the
method combination procedure a way to distinguish between methods.
4. Apply the effective method to the generic function arguments.
In the simplest implementation, the generic function would compute the
effective method each time. In practice, this is too inefficient and
most implementations do not execute this entire procedure every time a
generic function is called. Instead they employ a variety of
optimizations such as precomputation into tables, compilation, and/or
caching to speed things up. Some illustrative examples (not
exhaustive):
- Use a hash table keyed by the class of the arguments.
- Compile the Lisp form and save the resulting compiled-function.
- Recognize the Lisp form as an instance of a pattern of control
structure
and substitute a closure of a function that implements that
structure.
The Lisp form computed as the body for the effective method serves as a
more general interface. For example, a tool that determines which
methods are called and presents them to the user works by going through
the above procedure and then analyzing the form to determine which
methods it calls, instead of evaluating it.
STANDARD-METHOD-COMBINATION
The standard mechanism for computing the effective method recognizes
three qualifiers: :before, :after and :around. The combination rule is
as follows:
(this is described more succinctly below).
1) The principal method consists of the the invocation of the invokation
of all of the before methods, followed by the most specific unqualified
method, followed by all of the after methods. The value returned is
that returned by the unqualified method.
The before methods are invoked in order most-specific-first, and the
after methods in order most-specific-last. The unqualified method can
invoke a shadowed unqualified method by using call-next-method. If
there is no such shadowed method, an error is signalled.
2) If there are no :around methods, then the effective method is the
principal method. This is the usual case.
3) If there are :around methods, then the system constructs an ordered
list (most-specific-first) of :around methods followed by the principal
method. The most specific element of this list is invoked. If
call-next-method is invoked, then the next most specific one is invoked.
In the usual case this is done by every around method, and the principal
method is invoked as the last (nested) method of the list.
USER INTERFACE FOR DEFINING METHOD COMBINATION
The define-method-combination facility allows the programmer to
customize step 3 of the above procedure without having to worry about
what happens in the other steps. We will show how the standard method
combination method type is defined using this facility, as well as
several other useful examples. Step 2 of the procedure can be
customized by using the metaclass protocol to control the class
precedence order.
define-method-combination is a simple user interface to the meta-object
protocol, implicitly defining several methods. The primary method is
efectively defined by a form like:
(defmethod effective-method-body
((gf GENERIC-FUNCTION)
(combination-type (QUOTE type-name))
available-methods)
...)
where the arguments are specialized to the class GENERIC-FUNCTION and
the individual type-name.
(DEFINE-METHOD-COMBINATION name environmental-options . body)
environmental-options:=({method-option-keyword argument}*)
environmental-options are a set of options intended to be used by the
programming environment. Systems are free to ignore this argument, or
extend the set of options. Standard method-option-keywords are:
:DOCUMENTATION doc-string ;describes method combination type
:QUALIFIER-SET qualifier-test
qualifier-test:=fn-name ;predicate on qualifier list
:=({qualifier}*) ;list of allowed qualifiers
qualifier:=symbol
:=(symbol formatString)
where formatString is used by the environment to describe (to the user)
qualifed methods of this type. At least one of from the list of
qualifiers (if given) must appear in every non-null qualifier set.
:QUALIFIER-SET may appear more than once, and if so, at least one of the
tests must return true.
QUALIFIER-SET allows the environment to check for misspelling of
qualifiers and signal an error at method definiton time. An error is
signalled for a method that does not have a satisfactory qualifier list.
* Finding applicable methods
The body may include calls on FIND-METHODS to select subsets from the
ordered set of applicable methods (implicitly as an argument for these
macros). These include:
(FIND-METHODS &optional filter order)
where order is one of :MOST-SPECIFIC-FIRST or :MOST-SPECIFIC-LAST and
filter is an expression composed with special forms:
symbol ; matches a qualifier list containing symbol
(FILTER a1 a2 ...) ; matches a list equal to (a1 a2 ...)
; * can be used to match any item (or tail)
(FILTER-AND {qualifier-form}+)
(FILTER-OR {qualifier-form}+)
(FILTER-NOT qualifier-form)
(FILTER-TEST function) ;function is predicate on method-qualifier
list
The value returned by FIND-METHODS is an ordered list of method-objects.
* Constructing the effective-method-form
The form constructed can contain calls on standard functions (macros)
that hide implementation details from the user.
MAKE-METHOD-CALL method-list &key :operator :around
Returns a form whose car is operator (default is progn) and whose cdr is
forms that call the methods. If proclaim-identity-with-one-argument of
the operator has been done, and the length of method-list is 1, returns
just a form that calls the one method. If method-list is nil, returns
nil.
If around is true (default is false), returns a form that calls the first
method and arranges for call-next-method to reach the rest of the methods,
in the order they appear in method-list. In this case :operator cannot be
specified.
MAKE-METHOD-FROM-FORM form
Returns an object that acts like a method whose body is the form.
Informally and imprecisely this could be described as "the method version
of lambda".
METHOD-QUALIFIERS method
Returns a list of the method's qualifiers. This is particularly useful
when the qualifier-pattern contains *s, to find what they matched.
METHOD-COMBINATION-ERROR format-string &rest args
Either signals an error or prints a warning, depending on context. Adds
contextual information to the message. This should be used instead of
ERROR or WARN to signal errors, such as too many or too few methods
defined, because the type of error message appropriate in a given
situation is a function of the programming environment. Using this
abstraction ensures portability.
WRAP-AROUND-METHODS around-methods form
A combination of make-method-call and make-method-from-form that puts
:around methods around a form. This only exists for convenience, to
encourage programmers of new method-combination types to support :around
methods.
(defun wrap-around-methods (around-methods form)
(if around-methods
(make-method-call (append around-methods
(list (make-method-from-form form)))
:around t)
form))
.
EXAMPLES:
(define-method-combination :standard
(:documentation "Standard combination for generic-functions"
:qualifier-set
(:before :after
(:around "Methods that can shadow all others")))
`(wrap-around-methods
(find-methods :around)
(multiple-value-prog2
(make-method-call (find-methods :before))
(make-method-call (find-methods NIL) :around t)
(make-method-call (find-methods :before :most-specific-last)))))
(define-method-combination :and (:qualifier-set :and)
'(make-method-call (find-methods :and) :operator 'and))
>>> DESIGN RATIONALE:
The functions make-method-call and make-method-from-form exist not only
for convenience, but to conceal the implementation-dependent method
calling sequence details. This gives implementations the freedom to do
special optimizations, which may depend on the argument list of the
generic function and on the particular set of available methods. This
will become especially important if in the future we allow discrimination
on optional arguments.
The optimizations are hidden in the method make-discriminating-function
on generic function.
The functions make-method-call and make-method-from-form can only be
called from the body forms of define-method-combination. Their operation
depends on hidden state variables that contain the
implementation-dependent calling sequence details. It seems cleaner to
hide this stuff completely, by passing it around the user's
method-combination routine in dynamic variables, rather than making it
visible as an argument to the user's method-combination routine.
Why have a :around keyword to make-method-call, instead of using
:operator with a macro that does the call-next-method stuff? The
latter technique is not as flexible because it doesn't have access
to the method meta-objects, only to the Lisp forms that invoke the
method functions. Note that we have avoided specifying anything
about those Lisp forms; they are completely implementation-dependent
to allow maximum freedom for optimization.
∂02-Jan-87 2231 RPG Class Precedence List
To: common-lisp-object-system@SAIL.STANFORD.EDU
This message is long because there are a lot of examples of code running
at the end.
I've been searching for a way to explain the class precedence list
computation that is simpler than the existing explanations. I think we
can explain it fairly well if we relax, a bit, the requirements of
implementations, though we can certainly recommend that implementations go
the extra distance. What I'm proposing is a subset of the behavior that
the Moon algorithm has, but it is simple to explain and understand.
Here it is. We represent a partial order as a set of pairs, (x,y), such
that (x,y) indicates that x<y. Here are the assumed rules of the relation
<.
If x<y and y<z then x<z (transitivity)
If x<y then it is not the case that y<x (asymmetry)
It is not the case that x<x (irreflexivity)
If x<y we'll say that ``x precedes y.'' We then define a partial order on
the components of a class, C1, as follows. Let CL be the components of C1.
If D is a direct superclass of C, where C is in CL, then (C,D) is in the
partial order. If D1 and D2 are direct superclasses of C, where C is in
CL, such that D1 precedes D2 in the local precedence order, then
(D1,D2) is in the partial order. (Note, these correspond to Moon's rules 1
and 2, but we explicitly list the pairs of relations, and we deal with
direct superclasses only.)
Now we topologically sort the elements of CL. This is done as follows.
Select a class C that is not preceded by any other. Put it first in the order.
Remove C from CL and remove all pairs that mention it. This new CL is again
partially ordered by the new pairs. Select a C that is not preceded by
any other and put it next in the order. Continue until CL is empty.
The only way that the algorithm could fail, if there really was a partial
order to start with, would be if there were elements in CL at some point
and every C in CL was preceded by another. If this were true, we could
construct an arbitrary sequence, C1, C2, ... such that Cj+1<Cj. By
transitivity, for all j,k s.t. j<k, Ck<Cj, which implies that Cj is not
equal to Ck. But CL is finite, so some Cj=Ck for some j,k s.t. j<k. This
is a contradiction.
So, if the algorithm fails, we did not have a partial order, which means that
the local precedence order and the lattice order are inconsistent. The algorithm
does signal an error when this happens.
Topological sort runs in C1*M+C2*N time where M is the number of ordered pairs
and N is the number of objects in CL, C1 and C2 some constants.
I hacked this together, and it is 27 lines of code once the data structure
is built. Building the data structure incrementally from a series of
DEFCLASS1's as Moon uses in his examples is another 25 lines of so of code.
The total file is 84 lines long, including the DEFSTRUCT and the code to
make MacLisp think it's Common Lisp enough to run the rest (blush, I
have no Common Lisp to use on SAIL).
The code is an approximate translation of Knuth's algorithm on page 262 of
vol 1 (first edition). It takes the precise DEFCLASS's that define the
sublattice, but it's intended to only illustrate the algorithm at work.
If there are several total orders, the result of the topological sort depends
on the order that the algorithm selects classes that are not preceded by
any others. This depends, generally, on the order that the DEFCLASS's were
evaluated.
I propose that we require implementations to select a total order using an
implementation of topological sort, and that we encourage implementations
to signal an error when several total orders are possible. They can do
this using Moon's algorithm, for example, or by using the topological sort
and having the program notice when there are several classes not preceded
by others from which to select. It could backtrack and determine all of
them, I suppose.
I think this is simpler because many people know topological sort already,
they can understand the partial order in terms of these simple pairs, and
the topological sort algorithm can be explained in a paragraph. People can
also easily see where the non-determinism comes in if there are several
total orders. (Note that most people would know the algorithm after
reading the specification of the partial order as those pairs and seeing
the phrase ``now topologically sort.'')
Here it is running on some examples Moon, Danny, Gregor, and who knows who
else sent out (notice I changed the name of DEFCLASS1 to DEFCLASS). TOP
means the top of the lattice.
(defclass c1 (c2 c6 c5) ())
(defclass c2 (c3 c4) ())
(defclass c3 (c5) ())
(defclass c4 (c6) ())
(defclass c5 (top) ())
(defclass c6 (top) ())
(topologically-sort) = (C1 C2 C3 C4 C6 C5 TOP)
;;; Here are the partial order defining pairs for the above example:
;;; (c1,c2)(c1,c6)(c1,c5)(c2,c6)(c6,c5)(c2,c3)(c2,c4)(c3,c4)
;;; (c3,c5)(c4,c6)(c5,top)(c6,top)
(defclass c2 (c3 c4) ())
(defclass c3 (c5) ())
(defclass c4 (c6) ())
(defclass c5 (top) ())
(defclass c6 (top) ())
(topologically-sort) = (C2 C3 C5 C4 C6 TOP)
(defclass c1 (c3 c2) ())
(defclass c2 (c3) ())
(defclass c3 (top) ())
(topologically-sort) = Inconsistent Lattice
(defclass c1 (top) ())
(defclass c2 (top) ())
(defclass c3 (top) ())
(defclass c4 (c1 c2) ())
(defclass c5 (c3 c2) ())
(defclass c6 (c4 c5) ())
(topologically-sort) = (C6 C4 C5 C1 C3 C2 TOP)
(defclass c1 (top) ())
(defclass c2 (top) ())
(defclass c3 (top) ())
(defclass d4 (c3 c2) ())
(defclass d5 (c2) ())
(defclass d6 (c3 c2 d5 d4) ())
(topologically-sort) = Inconsistent Lattice
(defclass c1 (top) ())
(defclass c2 (top) ())
(defclass c3 (top) ())
(defclass e1 (c1) ())
(defclass e2 (c2) ())
(defclass e3 (c3) ())
(defclass e4 (e3 e2 e1) ())
(defclass e5 (c1 c2) ())
(defclass e6 (c2 c3) ())
(defclass e7 (e5 e6 e4) ())
(topologically-sort) = (E7 E5 E6 E4 E3 E2 E1 C1 C2 C3)
(defclass c1 (top) ())
(defclass c2 (top) ())
(defclass d1 (c1) ())
(defclass d2 (c2) ())
(defclass e1 (d1 d2) ())
(topologically-sort) = (E1 D1 D2 C1 C2 TOP)
(defclass c1 (top) ())
(defclass c2 (top) ())
(defclass c3 (top) ())
(defclass d1 (c1 c2) ())
(defclass d2 (c1 c3) ())
(defclass e1 (d1 d2) ())
(topologically-sort) = (E1 D1 D2 C1 C3 C2 TOP)
(defclass c2 (top) ())
(defclass c3 (top) ())
(defclass d4 (c3 c2) ())
(defclass d5 (c2) ())
(defclass d6 (c3 c2 d5 d4) ())
(topologically-sort) = Inconsistent Lattice
(defclass o (top) ())
(defclass b1 (o) ())
(defclass b2 (o) ())
(defclass b3 (o) ())
(defclass b4 (o) ())
(defclass ex1-1 (b1 b3 b4) ())
(defclass ex1-2 (b2 b3) ())
(defclass example-1 (ex1-1 ex1-2) ())
(topologically-sort) = (EXAMPLE-1 EX1-1 EX1-2 B1 B2 B3 B4 O TOP)
(defclass o (top) ())
(defclass b1 (o) ())
(defclass b2 (o) ())
(defclass b3 (o) ())
(defclass ex2-1 (b1) ())
(defclass ex2-2 (b2) ())
(defclass ex2-3 (b3) ())
(defclass example-2 (ex2-1 ex2-2 ex2-3) ())
(topologically-sort) = (EXAMPLE-2 EX2-1 EX2-2 B1 EX2-3 B2 B3 O TOP)
(defclass d0 (top) ())
(defclass d1 (top) ())
(defclass d2 (top) ())
(defclass d3 (top) ())
(defclass e (d0 d1) ())
(defclass f (d1 d2 d3) ())
(defclass g (d1 d2) ())
(defclass h (d0) ())
(defclass foo (e f g h) ())
(topologically-sort) = (FOO E F G H D0 D1 D2 D3 TOP)
(defclass d1 (top) ())
(defclass d2 (top) ())
(defclass d3 (top) ())
(defclass d4 (d3 d2) ())
(defclass d5 (d2) ())
(defclass d6 (d3 d2 d5 d4) ())
(topologically-sort) = Inconsistent Lattice
(defclass g1 (top) ())
(defclass g2 (top) ())
(defclass g3 (top) ())
(defclass g4 (top) ())
(defclass g5 (g1 g2) ())
(defclass g6 (g2 g3) ())
(defclass g7 (g3 g4) ())
(defclass g8 (g4 g5 g6 g7) ())
(topologically-sort) = Inconsistent Lattice
(defclass this (is much) ())
(defclass is (too) ())
(defclass much (fun!) ())
(defclass too () ())
(defclass fun! () ())
(topologically-sort) = (THIS IS TOO MUCH FUN!)
-rpg-
∂03-Jan-87 1529 Moon@STONY-BROOK.SCRC.Symbolics.COM STANDARD-TYPE-CLASS
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 3 Jan 87 15:28:51 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 34452; Sat 3-Jan-87 18:28:05 EST
Date: Sat, 3 Jan 87 18:27 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: STANDARD-TYPE-CLASS
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 31 Dec 86 18:14 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870103182719.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
I agree with the conclusions Dick reached in the referenced message.
I only have one thing to add, which is to make sure that we don't lose
sight of the original issue that brought this up (this time), which was
to clarify the explanation of such things as which classes are not valid
as superclasses in a DEFCLASS form. This is less ethereal than writing
programs that reason about the Lisp implementation, but not less important.
∂03-Jan-87 1537 Moon@STONY-BROOK.SCRC.Symbolics.COM Terminology: lattice
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 3 Jan 87 15:37:46 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 34456; Sat 3-Jan-87 18:36:57 EST
Date: Sat, 3 Jan 87 18:36 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Terminology: lattice
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 30 Dec 86 00:11 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870103183609.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 29 Dec 86 2111 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Moon briefly raises the issue of the term ``lattice.'' The class lattice is
not simply a lattice: The local ordering of direct superclasses matters.
However, the class lattice is, then, a lattice with some additional properties.
A quick breeze through my MacLane and Birkoff reveals there is no existing
name for what we have. I believe we can still use the term ``lattice,'' but
the figures Moon mentions ought to be altered as he suggests.
That's OK with me.
∂03-Jan-87 1600 Moon@STONY-BROOK.SCRC.Symbolics.COM terminology confusion: subclass, superclass
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 3 Jan 87 16:00:39 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 34460; Sat 3-Jan-87 18:59:51 EST
Date: Sat, 3 Jan 87 18:59 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: terminology confusion: subclass, superclass
To: common-lisp-object-system@SU-AI.ARPA
In-Reply-To: <861228185506.1.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<861229-171604-2561@Xerox>,
<861229-183348-2667@Xerox>,
The message of 30 Dec 86 00:11 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>,
<861230-101538-2927@Xerox>,
<861230-105602-300@Xerox>,
The message of 30 Dec 86 15:36 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>,
<861230-131351-1097@Xerox>
Message-ID: <870103185905.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
This message is a bit long, but I thought it was a good idea to
gather all the discussion on the subject into one place.
Date: Sun, 28 Dec 86 18:55 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
We need consistent terminology for distinguishing between the direct
parents of a class and the transitive closure of parentage; similarly
in the child direction. Right now the document sometimes uses "superclass"
and "subclass" to mean only the directly related classes, and uses
"component" to mean "superclass↑n, 0<=n" and "dependent" to mean
"subclass↑n, 0<=n". In other places the document uses "superclass" to
mean the transitive closure and "direct superclass" to mean the directly
related classes, and similarly for "subclass" and "direct subclass".
We need to be consistent about this. I believe the component/dependent
terminology is clearer, because it avoids using a single word to mean
two things, but other opinions are welcome.
In one message of 29 Dec, RPG agreed with the components/dependents terminology
but in a later message he changed his mind. I didn't save a reference to
the first message, hence this note.
Date: 29 Dec 86 17:15 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
I don't like the term component at all. It suggests a part hierarchy,
and for me any inheritance goes the wrong way; that is, components
inherit features from their container not the other way. For example, a
car door, a component of a car, is the same color as the car (usually).
Well, one could just as well say that the color of the car is determined by
the color of its various parts, such as doors, fenders, etc. However, the
point about the part hierarchy is well taken.
Dependent is also a misleading word because of its usage wrt interface
dependencies where a view of an object is a dependent on the state of
the object itself.
I suggest instead consistently use the term direct super(sub)class, or
local super(sub)class versus the unmodified one to indicate the closure.
This is okay with me as long as it is consistent. However, it seems evident
from the present state of the document that it's very easy to fall into the
trap of saying "superclass" when you mean "direct superclass", which can
confuse the reader. It would help if we had a two-word phrase for the
transitive closure, so that any time the word "superclass" stands alone
we know it is ambiguous. I don't have a suggestion, but perhaps someone
more mathematically inclined than I can suggest a term.
Date: 29 Dec 86 18:33 PST
From: Masinter.pa@Xerox.COM
using subclass for transitive closure of direct subclass and superclass
for transitive closure of direct superclass seems in my memory to be
more prevalent at least in the Object Oriented Programming literature.
That it uses a single word to mean two things is not so serious since
there is a direct relationship (as opposed to just "a relationship")
between the two things. To use the mathematical analogy to its fullest,
"A is a subclass of B" should be allowed when A = B, and "A is a proper
subclass of B" be used to describe the situation where A /= B.
Date: 29 Dec 86 2111 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
I believe we should distinguish immediate super/subclasses from
the transitive closure of those relationships. I don't believe
component/dependent are appropriate for the names of the transitive
closures.
For the moment I will call these relations superclass, subclass, superclass*,
and subclass*. Also, I will use these words as nouns to refer to objects that
bear the appropriate relationships to a given class.
I completely agree that the words for the relationships should also be used
as nouns referring to objects of the relationships.
A component is a constituent part or ingredient. A superclass* might not be
a constituent part of a class, because every aspect of it is shadowed.
A dependent is something that relies on or is subject to something else.
Again, a dependent might not depend on the superclass*, because everything
is shadowed.
Why doesn't the same argument say that a superclass* isn't a "real"
superclass*, because it happens that nothing is really inherited from
it? Furthermore, if a new method were added to the superclass*, for a
new generic function, then suddenly there would be something that was
inherited and wasn't fully shadowed, so the argument is very weak. I
don't think this special case gives us any guidance on how to choose
terminology.
``Component'' and ``dependent'' are not related words, and many people
who see the two together might not guess that one is the dual of the
other.
This is a fair to good argument.
I think that we should use the terminology:
Term in this Message = New Term
superclass* = superclass
superclass = direct superclass
subclass* = subclass
subclass = direct subclass
Date: 30 Dec 86 10:15 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
I agree that it would be good to consistently use the terms in column New Term.
Date: 30 Dec 86 10:55 PST
From: Masinter.pa@Xerox.COM
I agree with the New Term naming. I would like to add
superclass+ = proper superclass
subclass+ = proper subclass
Yes, this is important.
Date: 30 Dec 86 1236 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Would you prefer to use the term ``proper superclass''
or would you prefer to define that a class is not a superclass
of itself?
Date: 30 Dec 86 13:13 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
I prefer to say that a class is not a superclass of itself.
It's very important to have names for "superclass↑n, 0<=n" and
"subclass↑n, 0<=n", the improper transitive closures. That was the
motivation for my suggestion of "component" and "dependent", since
people often feel that "superclass" must mean the same as "proper
superclass".
The only
use of proper might come up in testing, where we use the terminology of
types. (SUBTYPEP 'object 'object) and (SUBTYPEP 'class 'object) are
both true.
Ah, since Common Lisp already defines that "subtype" is different from
"proper subtype", it makes sense for the object extension to Common Lisp
to define that "subclass" is different from "proper subclass" (and ditto
for "superclass").
We need a function that will take two classes and return T if
the first is equal to or a subclass of the second. Should this be named
SUBCLASSP?
Well, it certainly can't be named SUBCLASSP if "subclass" means the same
as "proper subclass", nor if "subclass" means the same as "direct subclass".
This is the same as my terminological argument about Lisp TYPEP meaning the
same as English "is a". I'm not actually sure whether we need that function,
or can just use SUBTYPEP, but that's an independent issue.
My conclusion from all this is that we need consistent names for the six
concepts mentioned above, and I'm willing to drop the component / dependent
terminology in favor of completely consistent use of:
xxx subclass n>=0
proper subclass n>=1
direct subclass n=1
direct superclass n=1
proper superclass n>=1
xxx superclass n>=0
I'm looking for suggestions for the word xxx. If we really can't think of
anything, that word could be omitted.
∂03-Jan-87 1749 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: :allocation slot-option issues
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 3 Jan 87 17:49:24 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 34471; Sat 3-Jan-87 20:48:35 EST
Date: Sat, 3 Jan 87 20:47 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: :allocation slot-option issues
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <861231-101817-1327@Xerox>
Message-ID: <870103204740.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 31 Dec 86 10:16 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
(1) The document currently says
If the allocation type is :class, storage for the slot is
allocated in the class object created by the defclass form. The
value of the slot is shared by all instances of the class. Any
subclass of this class will share this single slot unless the
defclass form for that subclass specifies a slot of the same
name.
This is okay, but points up an inconsistency between
instance-variables and class-variables. Repeating the slot
declaration of an instance variable does not create two separate
slots, but repeating the slot declaration of a class variable does.
I'm sure Alan Snyder would say that we should change instance
variables to do the same as class variables, but I prefer to wonder
if this indicates that something about class variables is broken.
This is not the same as my model. Repeating the slot declaration of a
class variable does not create two separate slots accessible from any
particular instance.
That's true, given the qualifier "from any particular instance."
It creates a new one that overrides the one that
would be inherited. This is the same model as instance variables as far
as I am concerned.
I don't see how you can say it's the same model. With instance variables,
there is no overriding of a slot that would otherwise be inherited; there
is only one slot. I suppose it must all be in how you look at it, but it
sure looks inconsistent to me.
I like to think (talk about) the access scope of class and instance
variables (whoops I should say slots):
1) There is one variable by any name accessible from an instance.
2) It is the one nearest in scope. If there is an instance variable
by that name, then it is the one, else it is the one in the class of the
instance or the most specific superclass of that class. This is the
same kind of nesting one gets in instantiation of function calls with
lexical scoping. If there is a local variable in the function, the
local value in the activation is accessed, else the nested scopes
containing the function definition are searched. I think the analogy
with inherited classes is very strong. Another analogy is to think of
classes as providing descriptions of sets, and subclasses describing
instances of subsets. Then the class variables are shared abong all
instances of the set.
The analogy to lexical nesting for class variables is good, I found it
helpful. It doesn't apply to instance variables, though, which is another
way of saying the same thing as my inconsistency complaint.
Several months ago I remember we discussed splitting
:allocation :class into :allocation :per-class and :allocation
:shared (or some names like that) to address this problem.
:per-class slots get a new copy for each dependent subclass,
whereas :shared slots are shared among all dependent subclasses,
even if the slot declaration is repeated. I think either the
discussion was before this group got started or else it quickly
dropped out of sight; I can't find it in any mail archives. Can we
open this issue and discuss the pros and cons of making this change?
Neither of :per-class or :shared as you describe it has the semantics I
mentioned. Perhaps it would be useful to have an option
:this-direct-class-only (meaning the class slot was accessible only to
instances of this direct class), but I find that confusing with respect
to the inheritance story.
:this-direct-class-only isn't the same as either of the ones I
mentioned, assuming that you meant to say that it doesn't inherit at
all. :per-class is inherited, but creates a new slot each time it is
inherited. :shared never creates a new slot, it always inherits the
same slot. It's true that neither of these has the semantics you
mentioned.
So we actually have four options for class variables to consider.
I'll label them with the names that happen to have been used, with no
implication that I think these are the right names:
:this-direct-class-only -- never inherited
:per-class -- inheritance never shares
:class -- inheritance shares unless shadowed
:shared -- inheritance always shares
As I said at the beginning of this conversation, the current definition
is okay with me, but I think it's inconsistent and so I have to wonder
whether it's really okay; maybe it's only okay with me because I happen
not to have much interest in class variables.
Perhaps this issue should be combined with the one of defining precisely
the inheritance behavior of all the class options and slot options,
something we have never done. I'd rather someone else be the leader on
that issue, since I already have plenty of work to do, but I'm willing to
make a proposal on it if no one else will.
∂03-Jan-87 1835 RPG Terminology
To: common-lisp-object-system@SAIL.STANFORD.EDU
I've just completed a relatively careful terminology pass over the
concepts file, paying close attention to superclass, direct superclass
etc. The term I really miss having and which makes for a lot of wording
headaches, is ``superclass or equal,'' a parallel to ``less than or
equal.'' This is Moon's superclass↑n, n non-negative. I believe the
proper term in lattice theory is ``filter.'' That is, the class itself and
all its superclasses form a filter over the set consisting of that
singleton class. This is not very intuitive (plus, I might be wrong).
The reason that ``superclass'' is not a misnomer as ``component''
might be is that it is abstract, meaning exactly that is it a
class that is the direct ancestor of the class, or the direct
ancestor of the direct ancestor, etc. That is, it is too abstract to
have an intuitive meaning outside of the hierarchy (sic).
-rpg-
∂04-Jan-87 1251 RPG Very Dull Message About Class Precedence Lists
To: common-lisp-object-system@SAIL.STANFORD.EDU
For those who are actively thinking about this issue, here is a followup
on my last message about topological sort. It mostly contains a bunch of
runs of a slightly modified algorithm. The modifications are that it now
reports when multiple orders are possible, and, when there is a choice
between several classes with no predecessors, the algorithm selects the
one that appear first in a preorder treewalk from the class for which the
class precedence list is being computed to the top of the lattice (viewed
as a tree). I believe that this algorithm produces the same results as
the New Flavors algorithm, but it is easier to explain: 1. Compute the
partial order relations; 2. topologically sort; 3. when topological sort
has a choice of several classes to put next, select according to preorder.
(init)
(defclass c1 (c2 c6 c5) ())
(defclass c2 (c3 c4) ())
(defclass c3 (c5) ())
(defclass c4 (c6) ())
(defclass c5 (top) ())
(defclass c6 (top) ())
(topologically-sort 'c1)
= (C1 C2 C3 C4 C6 C5 TOP)
(init)
(defclass c2 (c3 c4) ())
(defclass c3 (c5) ())
(defclass c4 (c6) ())
(defclass c5 (top) ())
(defclass c6 (top) ())
(topologically-sort 'c2)
= (C2 C3 C5 C4 C6 TOP) Multiple orders possible
(init)
(defclass c1 (c3 c2) ())
(defclass c2 (c3) ())
(defclass c3 (top) ())
(topologically-sort 'c1)
= Inconsistent Lattice
(init)
(defclass c1 (top) ())
(defclass c2 (top) ())
(defclass c3 (top) ())
(defclass c4 (c1 c2) ())
(defclass c5 (c3 c2) ())
(defclass c6 (c4 c5) ())
(topologically-sort 'c6)
= (C6 C4 C1 C5 C3 C2 TOP) Multiple orders possible
(init)
(defclass c1 (top) ())
(defclass c2 (top) ())
(defclass c3 (top) ())
(defclass d4 (c3 c2) ())
(defclass d5 (c2) ())
(defclass d6 (c3 c2 d5 d4) ())
(topologically-sort 'd6)
= Inconsistent Lattice
(init)
(defclass c1 (top) ())
(defclass c2 (top) ())
(defclass c3 (top) ())
(defclass e1 (c1) ())
(defclass e2 (c2) ())
(defclass e3 (c3) ())
(defclass e4 (e3 e2 e1) ())
(defclass e5 (c1 c2) ())
(defclass e6 (c2 c3) ())
(defclass e7 (e5 e6 e4) ())
(topologically-sort 'e7)
= (E7 E5 E6 E4 E3 E2 E1 C1 C2 C3 TOP)
(init)
(defclass c1 (top) ())
(defclass c2 (top) ())
(defclass d1 (c1) ())
(defclass d2 (c2) ())
(defclass e1 (d1 d2) ())
(topologically-sort 'e1)
= (E1 D1 D1 C2 C2 TOP) Multiple orders possible
(init)
(defclass c1 (top) ())
(defclass c2 (top) ())
(defclass c3 (top) ())
(defclass d1 (c1 c2) ())
(defclass d2 (c1 c3) ())
(defclass e1 (d1 d2) ())
(topologically-sort 'e1)
= (E1 D1 D2 C1 C2 C3 TOP) Multiple orders possible
(init)
(defclass c2 (top) ())
(defclass c3 (top) ())
(defclass d4 (c3 c2) ())
(defclass d5 (c2) ())
(defclass d6 (c3 c2 d5 d4) ())
(topologically-sort 'd6)
= Inconsistent Lattice
(init)
(defclass b1 (top) ())
(defclass b2 (top) ())
(defclass b3 (top) ())
(defclass b4 (top) ())
(defclass ex1-1 (b1 b3 b4) ())
(defclass ex1-2 (b2 b3) ())
(defclass example-1 (ex1-1 ex1-2) ())
(topologically-sort 'example-1)
= (EXAMPLE-1 EX1-1 B1 EX1-2 B2 B3 B4 TOP) Multiple orders possible
(init)
(defclass b1 (top) ())
(defclass b2 (top) ())
(defclass b3 (top) ())
(defclass ex2-1 (b1) ())
(defclass ex2-2 (b2) ())
(defclass ex2-3 (b3) ())
(defclass example-2 (ex2-1 ex2-2 ex2-3) ())
(topologically-sort 'example-2)
= (EXAMPLE-2 EX2-1 B1 EX2-2 B2 EX2-3 B3 TOP) Multiple orders possible
(init)
(defclass d0 (top) ())
(defclass d1 (top) ())
(defclass d2 (top) ())
(defclass d3 (top) ())
(defclass e (d0 d1) ())
(defclass f (d1 d2 d3) ())
(defclass g (d1 d2) ())
(defclass h (d0) ())
(defclass foo (e f g h) ())
(topologically-sort 'foo)
= (FOO E F G H D0 D1 D2 D3 TOP)
(init)
(defclass d1 (top) ())
(defclass d2 (top) ())
(defclass d3 (top) ())
(defclass d4 (d3 d2) ())
(defclass d5 (d2) ())
(defclass d6 (d3 d2 d5 d4) ())
(topologically-sort 'd6)
= Inconsistent Lattice
(init)
(defclass g1 (top) ())
(defclass g2 (top) ())
(defclass g3 (top) ())
(defclass g4 (top) ())
(defclass g5 (g1 g2) ())
(defclass g6 (g2 g3) ())
(defclass g7 (g3 g4) ())
(defclass g8 (g4 g5 g6 g7) ())
(topologically-sort 'g8)
= Inconsistent Lattice
(init)
(defclass this (is much) ())
(defclass is (too) ())
(defclass much (fun!) ())
(defclass too (top) ())
(defclass fun! (top) ())
(topologically-sort 'this)
= (THIS IS TOO MUCH FUN!) Multiple orders possible
-rpg-
∂05-Jan-87 0857 Bobrow.pa@Xerox.COM Re: terminology confusion: subclass, superclass
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 08:57:07 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 08:46:49 PST
Date: 5 Jan 87 08:45 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: terminology confusion: subclass, superclass
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sat, 3 Jan 87 18:59 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870105-084649-3064@Xerox>
Moon says:
"My conclusion from all this is that we need consistent names for the
six
concepts mentioned above, and I'm willing to drop the component /
dependent
terminology in favor of completely consistent use of:
xxx subclass n>=0
proper subclass n>=1
direct subclass n=1
direct superclass n=1
proper superclass n>=1
xxx superclass n>=0
I'm looking for suggestions for the word xxx. If we really can't think
of
anything, that word could be omitted."
I agree. I sugest we use the phrases "effective subclass" and
"effective superclass" where we want to emphasize the possibility of
n=0, and allow "subclass" and "superclass" to mean that as well.
danny
∂05-Jan-87 0956 Bobrow.pa@Xerox.COM Re: Class Precedence List
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 09:56:45 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 09:48:04 PST
Date: 5 Jan 87 09:46 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Class Precedence List
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 02 Jan 87
22:31 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870105-094804-3149@Xerox>
I think this is simpler because many people know topological
sort already, they can understand the partial order in terms of
these simple pairs, and the topological sort algorithm can be
explained in a paragraph. People can also easily see where the
non-determinism comes in if there are several total orders. (Note
that most people would know the algorithm after reading the
specification of the partial order as those pairs and seeing the
phrase ``now topologically sort.'')
I don't believe that this is clearer than the explanation Gregor and I
gave, which in about the same amount of code used by RPG, computes the
data structure, computes the preferred (preorder walk) topological sort,
and provides appropriate error messages.
Since the usual case with multiple inheritance of independent mixins
(the usual way to use them) is that multiple sorts are possbile, it
seems inappropriate to warn the user of such a case. But perhaps the
best way to describe things would be to take my last message on the
subject, and append the topological sort explanation for those who
prefer things that way.
danny
∂05-Jan-87 0957 Bobrow.pa@Xerox.COM Re: STANDARD-TYPE-CLASS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 09:56:51 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 09:55:28 PST
Date: 5 Jan 87 09:54 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: STANDARD-TYPE-CLASS
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sat, 3 Jan 87 18:27 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870105-095528-3156@Xerox>
I agree with the conclusions Dick reached in the referenced
message.
After several more discussions around here, I am willing to settle for
eliminating the use of the class-name "CLASS". I would call the top of
the hierarchy called ESSENTIAL-CLASS, the one the user usually gets be
DEFAULT-CLASS, and have the appropriate use of STANDARD-TYPE-CLASS and
BUILT-IN-CLASS. My reason is the pain of the circumlocution of the
phrase class CLASS, and the clearer meaning of saying that DEFAULT-CLASS
provides ...
I only have one thing to add, which is to make sure that
we don't lose sight of the original issue that brought this up
(this time), which was to clarify the explanation of such things as
which classes are not valid as superclasses in a DEFCLASS form.
This is less ethereal than writing programs that reason about the
Lisp implementation, but not less important.
I have somehow lost sight of this issue. Do you mean that
BUILT-IN-CLASS can never be a superclass of anything not a
BUILT-IN-CLASS? Namely BUILT-IN-CLASS is reserved for the implementer.
Is that the only restriction you have in mind?
danny
∂05-Jan-87 1150 Bobrow.pa@Xerox.COM Re: :allocation slot-option issues
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 11:50:34 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 11:07:52 PST
Date: 5 Jan 87 11:07 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: :allocation slot-option issues
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sat, 3 Jan 87 20:47 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870105-110752-3299@Xerox>
It creates a new one that overrides
the one that would be inherited. This is the same model as
instance variables as far as I am concerned.
I don't see how you can say it's the same model. With instance
variables, there is no overriding of a slot that would otherwise be
inherited; there is only one slot. I suppose it must all be in how
you look at it, but it sure looks inconsistent to me.
I like to think (talk about) the access scope of class
and instance variables (whoops I should say slots):
1) There is one variable by any name accessible from
an instance. 2) It is the one nearest in scope. If there is
an instance variable
by that name, then it is the one, else it is the one in
the class of the instance or the most specific superclass of
that class. This is the same kind of nesting one gets in
instantiation of function calls with lexical scoping. If there
is a local variable in the function, the local value in the
activation is accessed, else the nested scopes containing the
function definition are searched. I think the analogy with
inherited classes is very strong. Another analogy is to think
of classes as providing descriptions of sets, and subclasses
describing instances of subsets. Then the class variables are
shared abong all instances of the set.
The analogy to lexical nesting for class variables is good, I
found it helpful. It doesn't apply to instance variables, though,
which is another way of saying the same thing as my inconsistency
complaint.
I think it does apply to both class and instance variables. The
variables seen by an instance (and this is the critical phrase) are just
those described in all the classes it inherits from. (just as the
variables seen by an activiation are all of those in all scopes it
inherits from). The instance sees only one varible of any name (as does
an activation).
Some are stored locally, and some are shared (instance variables and
class variables vs local parameters and closure variables). All
instances see exctly one description of any variable. The most specific
description dominates (the one in the class nearest the front of the
class precedence list). Thus I am proposing that we have only one
:allocation option of this type :class. Following is my proposal for
the inheritance.
Specification of Inheritance
None of :reader :accessor :allocation or :initialize-only (if we still
have that) are inherited.
:initform is inherited if not overridden
:type is inherited, but we do not specify what the system does with it.
An open question is whether inheritance here should be a union
operation, or if the more specific type must always be a subtype of the
inherited one.
:initform is evaluated as follows
1) Exactly once for :allocation :instance at initialization time.
The value is stored in the instance.
2) At most once for :allocation :dynamic, :class
At first access for :dynamic and :class, unless first access is a
store.
The value of the initform is stored in the instance and class
respectively on this first access.
3) Each time for :allocation :none
An error is signalled when trying to store in a variable with
allocation :none
The :none option is most useful at the top of a hierarchy where one
expects some subclasses to allocate storage, but on wants to write
methods that can assume they can fetch a standard value. It can also be
used for subtractive inheritance at some significant cost.
danny
∂05-Jan-87 1151 Gregor.pa@Xerox.COM Re: STANDARD-TYPE-CLASS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 11:50:55 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 11:37:44 PST
Date: 5 Jan 87 11:37 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: STANDARD-TYPE-CLASS
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 5 Jan 87 09:54 PST
To: Bobrow.pa@Xerox.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM,
common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870105-113744-3348@Xerox>
This message addresses this issue of what to name the class currently
named class, and related issues.
The current proposal seems to be:
There is a class named essential-class, the english phrase "X is a
class" corresponds to (typep X 'essential-class). There is a class
named default-class, this is the kind of class defclass produces, it is
a subclass of essential-class. There is a class named built-in-class,
it is a subclass of essential-class.
I basically agree with this. But it seems to me that it might be a good
idea to use the name class instead of essential-class for the top of the
class hierarchy. This would make the english phrase "X is a class"
correspond to (typep x 'class). In addition, it would remove the use of
the somewhat confusing "ESSENTIAL-xxx" convention from the standard (I
confess that I use it all the time, but that doesn't mean that it isn't
confusing).
It seems to me that whatever convention we use here will be picked up by
a lot of other programs and programmers. I think that means we should
actually have a convention, with a consistent set of rules which are
explained in the rationale section.
∂05-Jan-87 1150 Bobrow.pa@Xerox.COM Some invariants
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 11:50:46 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 11:29:19 PST
Date: 5 Jan 87 11:29 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Some invariants
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
cc: Bobrow.pa@Xerox.COM
Message-ID: <870105-112919-3334@Xerox>
Here are some possible invariants and some arguments against them.
Which ones do you like?
(class-of (make-instance x)) = x
The class of the result of a make-instance is always the same as its
argument. A make-instance message could make a more specialized version
of itself, say as an environmental feature.
(not (eq (make-instance x) (make-instance x)))
This could usefully not be true if one of the initialization parameters
was a unique identifier (UID) that was supposed to identify the object
being created, and it already existed. Then the result of make-instance
should be the already existing object.
(eq (class-name (class-named x)) x)
This seems like it should be true, unless we make it such that classes
do not know their names, and the same class can have more than one name.
Is this useful? We could of course have a "hint" of a name in the class
for debugging purposes. This would make classes be first class
anonymous things as well.
∂05-Jan-87 1216 DLW@ALDERAAN.SCRC.Symbolics.COM Re: Class Precedence List
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 5 Jan 87 12:15:50 PST
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 35630; Mon 5-Jan-87 14:57:57 EST
Date: Mon, 5 Jan 87 14:59 EST
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Re: Class Precedence List
To: Bobrow.pa@Xerox.COM, RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870105-094804-3149@Xerox>
Message-ID: <870105145929.1.DLW@CHICOPEE.SCRC.Symbolics.COM>
Line-fold: No
Perhaps the X3J13 people, who'll be the first diverse group to take a
look at this stuff and give us feedback, will be able to provide some
useful data about which explanation turns out to be easier to
understand. I've found that it's sometimes hard to predict what other
people will find clear or not so clear -- when you yourself have spent a
lot of time on it, it gets hard to try to put yourself in the place of
someone who is seeing it for the first time. So you might consider
including both explanations and then asking for opinions. (I'm assuming
that this can be done without a lot of further writing effort beyond
what's already written -- I realize that there isn't much time to do a
significant extra writing.)
∂05-Jan-87 1233 Moon@STONY-BROOK.SCRC.Symbolics.COM Method Combination Proposal
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 5 Jan 87 12:33:09 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 35525; Mon 5-Jan-87 15:32:16 EST
Date: Mon, 5 Jan 87 15:30 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Method Combination Proposal
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <861231-172503-1727@Xerox>
Message-ID: <870105153057.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Danny, your letter arrived at a good time since I've been thinking about
method combination again. I hope we can finish up the method combination
issue this week. I think your letter can be divided into two parts:
first: the explanation of the overall framework and the design rationale;
second: the particular syntax of the define-method-combination macro. I
agree with pretty much everything in the first part, and I think it's
substantially improved over my version.
I don't think the second part is as good. Looking back over the old
discussion, the motivation for the find-methods scheme was stated to be
simplicity, but in each version it gets more and more complicated. I
don't think it really achieves its goal. Allow me to offer a few other
criticisms, briefly: The :qualifier-set option duplicates the
information in the arguments to find-methods, with a different syntax,
and with a different expressive power (unless one resorts to the escape
to a predicate function); this duplicate information will be highly
error-prone. The :qualifier-set syntax doesn't seem to allow a way to
say anything about unqualified methods and doesn't seem to have the
flexibility to deal with methods with more than one qualifier. The
examples are hard to understand since the :qualifier-set syntax used in
the :and example is not the same as the syntax described earlier, and
because the backquotes and commas are messed up.
The thing about my old proposed syntax for define-method-combination that I
never explained very well is the reason for dividing it into two parts.
The first part defines the meaning of the method qualifiers, while the
second part defines how the methods are glued together. It's important
that the definition of the method qualifiers is all in one place, and I
think it's important not to mix it up with other stuff. I realized last
week that most of the support functions are superfluous; this allows a
significant simplification of the design.
A survey of Symbolics object-oriented code shows that the form of standard
method combination with the primary methods in most-specific-last order is
not needed, so the standard method combination does not need to take any
arguments (another simplification relative to my earlier proposals). The
same survey showed that most-specific-last order is quite useful with some
kinds of method combination that invoke all the methods (rather than
shadowing), specifically progn, list, append, and, and or (this list is in
decreasing order of popularity). The survey also uncovered a user-defined
method combination type that takes &key arguments, hence my proposal still
includes arguments in the :METHOD-COMBINATION option to DEFGENERIC-OPTIONS,
even though the standard kind of method combination does not use them.
Here is my revised proposal for define-method-combination syntax. This
goes along with the first part of Danny's message, so I won't repeat
that. Lowercase Lisp words should be understood to be in italics.
(DEFINE-METHOD-COMBINATION name lambda-list [macro]
({(variable {qualifier-pattern}+ {keyword argument}*)}*)
{declaration | doc-string}*
{form}*)
name is a symbol, usable as a name for this in the :METHOD-COMBINATION
option to DEFGENERIC-OPTIONS. By convention, non-keyword, non-NIL symbols
are usually used.
lambda-list is an ordinary lambda-list, which receives any arguments given
in the :METHOD-COMBINATION option to DEFGENERIC-OPTIONS.
A list of method-group specifiers follows. These define all method
qualifiers that can be used with this type of method combination. Each
specifier contains a variable, one or more qualifier-patterns, and zero or
more keyword options. The variable is bound to a list of methods that
match at least one of the qualifier-patterns, in most-specific-first order.
Keyword options are described in the advanced facilities section below. A
method matches a qualifier-pattern if the method's list of qualifiers is
EQUAL to the qualifier-pattern, except that the symbol * in a
qualifier-pattern matches anything. Thus a qualifier-pattern can be the
empty list () (which matches unqualified methods), the symbol * (which
matches all methods), an undotted list, or a list that ends in a dotted
pair whose cdr is * (which matches any number of additional qualifiers).
Qualifier-patterns are tested in the order written, so if a method could
be a member of more than one method-group, it joins only the first such
group. If an applicable method does not match any qualifier-pattern, the
system reports an error, or a warning, that the method is not appropriate
for the kind of method-combination being used.
Declarations at the head of the body are positioned directly inside of
bindings created by the lambda-list, and outside of the bindings of the
method-group variables. If a doc-string is present, it documents the
method-combination type.
The value of the last form in the body is the Lisp form that specifies how
the methods are combined. Erroneous conditions detected by the body should be
reported with WARN; implementations will add any necessary contextual
information to the warning. It is permissible for an implementation to
define the functions WARN and MAKE-METHOD-CALL by enclosing the body forms
in a FLET.
MAKE-METHOD-CALL method-list &key :operator :around [function]
Returns a form whose car is operator (default is PROGN) and whose cdr is
a list of forms that call the methods. MAKE-METHOD-CALL can only be called
from the body of a DEFINE-METHOD-COMBINATION.
If :around is true (default is false) and the length of method-list is
greater than 1, the result is a form that calls the first method and
arranges for CALL-NEXT-METHOD to reach the rest of the methods, in the
order they appear in method-list. In this case :operator must not be
specified.
Each element of method-list can be either a method-object or a form. When
a form is given, it is converted into a method (conceptually by enclosing
it in a LAMBDA-expression) when necessary.
If method-list is NIL, the result is NIL. If method-list contains one
element and PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT of the operator has been
done, the result is just a form that calls the one method, with no
invocation of the operator.
As a convenience, if method-list is a method-object, it is automatically
converted to a one-element list of that method.
There are additional keywords mentioned under "Advanced Facilities".
METHOD-QUALIFIERS method [function]
Returns a list of the method's qualifiers. This is particularly useful
when the body forms perform additional filtering or processing of the
method-group lists. For example,
(setq methods (remove-duplicates methods
:from-end t
:key #'method-qualifiers
:test #'equal))
PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT symbol [function]
Tells the object system that a form (symbol form1) can be optimized to just
form1. Note that if symbol is a function (rather than a special operator)
the optimization is only strictly valid if form1 returns exactly one value.
This is not checked. PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT is intended to be
called at top level and is not intended to affect the compiler. Its main
purpose is to enable the optimization of using an existing method as the
effective method. The object system's optimizer knows about PROGN,
MULTIPLE-VALUE-PROG1, and MULTIPLE-VALUE-PROG2, as well as any operators
proclaimed with PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT.
MULTIPLE-VALUE-PROG2 form result-form {form}* [macro]
The obvious extension of MULTIPLE-VALUE-PROG1.
>>> EXAMPLES:
;The default method-combination technique
(define-method-combination standard ()
((around (:around))
(before (:before))
(primary ())
(after (:after)))
(make-method-call `(,@around
(multiple-value-prog2
,(make-method-call before)
,(make-method-call primary :around t)
,(make-method-call (reverse after))))
:around t))
(define-method-combination and ()
((methods () (:and)))
(make-method-call methods :operator 'and))
;A more complete version of the preceding
(define-method-combination and (&optional (order ':most-specific-first))
((around (:around))
(primary () (:and)))
(case order
(:most-specific-first)
(:most-specific-last (setq primary (reverse primary)))
(otherwise
(warn "~S is an invalid order.~@
:most-specific-first and :most-specific-last are the possible values."
order)))
(make-method-call `(,@around
,(make-method-call primary :operator 'and))
:around t))
>>> SHORT FORM:
(DEFINE-METHOD-COMBINATION name operator [doc-string]) [macro]
Defines name as a type of method combination that produces a Lisp form
(operator method-call method-call...). Operator can be the name of a
function, the name of a macro, or the name of a special form. This
alternate syntax of DEFINE-METHOD-COMBINATION is provided for convenience
and is recognized when the second subform is a non-null symbol. By
convention, name and operator are often the same symbol, but this is not
required.
This method-combination type recognizes unqualified methods and methods
with one qualifier, the keyword symbol with the same name as name, as
primary methods. It also recognizes methods with one qualifier, :around,
as auxiliary methods that behave the same as :around methods in standard
method combination.
A method-combination type defined this way always takes one optional
argument, order, defaulting to :most-specific-first. A value of
:most-specific-last reverses the order of the primary methods, without
affecting the order of the auxiliary methods.
The last example above is, in fact, an example of the macro expansion of
the short form expression (define-method-combination and and).
>>> ADVANCED FACILITIES:
These facilities could be included if we want a comprehensive standard, or
could be omitted for the time being if we prefer a stripped-down standard.
I've only included facilities whose usefulness has been demonstrated in
Flavors.
Keyword options for method-group specifiers in define-method-combination:
:ORDER -- the argument is a form evaluating to :MOST-SPECIFIC-FIRST or
:MOST-SPECIFIC-LAST. If it evaluates to any other value, the system issues
a warning. This is a convenience, to avoid having to write the CASE expression
seen in the last example above, and does not add any expressive power.
:DESCRIPTION -- the argument is a format-string used in (APPLY #'FORMAT
stream description (METHOD-QUALIFIERS method)). In most cases the
description will not contain any format directives. The description should
be concise (one or two words). If no description is specified, a default
description is chosen based on the variable name, the qualifier patterns,
and whether this method-group includes the unqualified methods. This
description mechanism tells programming environment tools the meaning of
method qualifiers.
Additional keyword arguments for MAKE-METHOD-CALL:
:ARGLIST list-of-forms
Uses the specified forms as the arguments to each method instead of
using the arguments to the generic function.
:APPLY list-of-forms
Same as :arglist except that the last form in the list evaluates to
a list of arguments and the call is made with apply rather than funcall.
You must not specify both :arglist and :apply.
This is a bit more complicated than it seems at first, because there are
three potentially different argument lists involved. (1) The arguments
supplied to the generic function. (2) The arguments passed from the
generic function to the methods. (3) The arguments actually received by a
method. (2) differs from (1) in certain proposals for discrimination on
optional arguments, such as the &generic-optional one and the :interface
one. (3) differs from (2) in implememtations that have a special calling
sequence for methods. The :arglist/:apply keywords for make-method-call
allow you to change the (2) arguments; any implementation-dependent
transformation from (2) to (3) still applies.
It is not a good idea to change arguments that are used for discrimination,
since this could cause a method to be called with an argument that does
not match its parameter specializer.
WITH-METHOD-ARGUMENT-ACCESSORS lambda-list &body body [macro]
This macro is convenient when changing the arguments passed to the methods.
Each parameter in lambda-list is bound to a form that accesses the
corresponding method argument, and then body is executed. These accessor
forms come from the hidden information mentioned above. Lambda-list must
match the (2) arguments mentioned above.
∂05-Jan-87 1237 Moon@STONY-BROOK.SCRC.Symbolics.COM Method Combination Proposal
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 5 Jan 87 12:37:28 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 35536; Mon 5-Jan-87 15:35:58 EST
Date: Mon, 5 Jan 87 15:34 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Method Combination Proposal
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <861231-172503-1727@Xerox>
Supersedes: <870105153057.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870105153453.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
[Please ignore the earlier version of this message. I forgot, when writing
the examples, that we had agreed back in October that it was an error to
have only auxiliary methods, a difference from Flavors. This version has
the examples corrected.]
Danny, your letter arrived at a good time since I've been thinking about
method combination again. I hope we can finish up the method combination
issue this week. I think your letter can be divided into two parts:
first: the explanation of the overall framework and the design rationale;
second: the particular syntax of the define-method-combination macro. I
agree with pretty much everything in the first part, and I think it's
substantially improved over my version.
I don't think the second part is as good. Looking back over the old
discussion, the motivation for the find-methods scheme was stated to be
simplicity, but in each version it gets more and more complicated. I
don't think it really achieves its goal. Allow me to offer a few other
criticisms, briefly: The :qualifier-set option duplicates the
information in the arguments to find-methods, with a different syntax,
and with a different expressive power (unless one resorts to the escape
to a predicate function); this duplicate information will be highly
error-prone. The :qualifier-set syntax doesn't seem to allow a way to
say anything about unqualified methods and doesn't seem to have the
flexibility to deal with methods with more than one qualifier. The
examples are hard to understand since the :qualifier-set syntax used in
the :and example is not the same as the syntax described earlier, and
because the backquotes and commas are messed up.
The thing about my old proposed syntax for define-method-combination that I
never explained very well is the reason for dividing it into two parts.
The first part defines the meaning of the method qualifiers, while the
second part defines how the methods are glued together. It's important
that the definition of the method qualifiers is all in one place, and I
think it's important not to mix it up with other stuff. I realized last
week that most of the support functions are superfluous; this allows a
significant simplification of the design.
A survey of Symbolics object-oriented code shows that the form of standard
method combination with the primary methods in most-specific-last order is
not needed, so the standard method combination does not need to take any
arguments (another simplification relative to my earlier proposals). The
same survey showed that most-specific-last order is quite useful with some
kinds of method combination that invoke all the methods (rather than
shadowing), specifically progn, list, append, and, and or (this list is in
decreasing order of popularity). The survey also uncovered a user-defined
method combination type that takes &key arguments, hence my proposal still
includes arguments in the :METHOD-COMBINATION option to DEFGENERIC-OPTIONS,
even though the standard kind of method combination does not use them.
Here is my revised proposal for define-method-combination syntax. This
goes along with the first part of Danny's message, so I won't repeat
that. Lowercase Lisp words should be understood to be in italics.
(DEFINE-METHOD-COMBINATION name lambda-list [macro]
({(variable {qualifier-pattern}+ {keyword argument}*)}*)
{declaration | doc-string}*
{form}*)
name is a symbol, usable as a name for this in the :METHOD-COMBINATION
option to DEFGENERIC-OPTIONS. By convention, non-keyword, non-NIL symbols
are usually used.
lambda-list is an ordinary lambda-list, which receives any arguments given
in the :METHOD-COMBINATION option to DEFGENERIC-OPTIONS.
A list of method-group specifiers follows. These define all method
qualifiers that can be used with this type of method combination. Each
specifier contains a variable, one or more qualifier-patterns, and zero or
more keyword options. The variable is bound to a list of methods that
match at least one of the qualifier-patterns, in most-specific-first order.
Keyword options are described in the advanced facilities section below. A
method matches a qualifier-pattern if the method's list of qualifiers is
EQUAL to the qualifier-pattern, except that the symbol * in a
qualifier-pattern matches anything. Thus a qualifier-pattern can be the
empty list () (which matches unqualified methods), the symbol * (which
matches all methods), an undotted list, or a list that ends in a dotted
pair whose cdr is * (which matches any number of additional qualifiers).
Qualifier-patterns are tested in the order written, so if a method could
be a member of more than one method-group, it joins only the first such
group. If an applicable method does not match any qualifier-pattern, the
system reports an error, or a warning, that the method is not appropriate
for the kind of method-combination being used.
Declarations at the head of the body are positioned directly inside of
bindings created by the lambda-list, and outside of the bindings of the
method-group variables. If a doc-string is present, it documents the
method-combination type.
The value of the last form in the body is the Lisp form that specifies how
the methods are combined. Erroneous conditions detected by the body should be
reported with WARN; implementations will add any necessary contextual
information to the warning. It is permissible for an implementation to
define the functions WARN and MAKE-METHOD-CALL by enclosing the body forms
in a FLET.
MAKE-METHOD-CALL method-list &key :operator :around [function]
Returns a form whose car is operator (default is PROGN) and whose cdr is
a list of forms that call the methods. MAKE-METHOD-CALL can only be called
from the body of a DEFINE-METHOD-COMBINATION.
If :around is true (default is false) and the length of method-list is
greater than 1, the result is a form that calls the first method and
arranges for CALL-NEXT-METHOD to reach the rest of the methods, in the
order they appear in method-list. In this case :operator must not be
specified.
Each element of method-list can be either a method-object or a form. When
a form is given, it is converted into a method (conceptually by enclosing
it in a LAMBDA-expression) when necessary.
If method-list is NIL, the result is NIL. If method-list contains one
element and PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT of the operator has been
done, the result is just a form that calls the one method, with no
invocation of the operator.
As a convenience, if method-list is a method-object, it is automatically
converted to a one-element list of that method.
There are additional keywords mentioned under "Advanced Facilities".
METHOD-QUALIFIERS method [function]
Returns a list of the method's qualifiers. This is particularly useful
when the body forms perform additional filtering or processing of the
method-group lists. For example,
(setq methods (remove-duplicates methods
:from-end t
:key #'method-qualifiers
:test #'equal))
PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT symbol [function]
Tells the object system that a form (symbol form1) can be optimized to just
form1. Note that if symbol is a function (rather than a special operator)
the optimization is only strictly valid if form1 returns exactly one value.
This is not checked. PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT is intended to be
called at top level and is not intended to affect the compiler. Its main
purpose is to enable the optimization of using an existing method as the
effective method. The object system's optimizer knows about PROGN,
MULTIPLE-VALUE-PROG1, and MULTIPLE-VALUE-PROG2, as well as any operators
proclaimed with PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT.
MULTIPLE-VALUE-PROG2 form result-form {form}* [macro]
The obvious extension of MULTIPLE-VALUE-PROG1.
>>> EXAMPLES:
;The default method-combination technique
(define-method-combination standard ()
((around (:around))
(before (:before))
(primary ())
(after (:after)))
;; Must have a primary method
(unless primary
(warn "A primary method is required."))
(make-method-call `(,@around
(multiple-value-prog2
,(make-method-call before)
,(make-method-call primary :around t)
,(make-method-call (reverse after))))
:around t))
(define-method-combination and ()
((methods () (:and)))
(make-method-call methods :operator 'and))
;A more complete version of the preceding
(define-method-combination and (&optional (order ':most-specific-first))
((around (:around))
(primary () (:and)))
;; Process the order argument
(case order
(:most-specific-first)
(:most-specific-last (setq primary (reverse primary)))
(otherwise
(warn "~S is an invalid order.~@
:most-specific-first and :most-specific-last are the possible values."
order)))
;; Must have a primary method
(unless primary
(warn "A primary method is required."))
(make-method-call `(,@around
,(make-method-call primary :operator 'and))
:around t))
>>> SHORT FORM:
(DEFINE-METHOD-COMBINATION name operator [doc-string]) [macro]
Defines name as a type of method combination that produces a Lisp form
(operator method-call method-call...). Operator can be the name of a
function, the name of a macro, or the name of a special form. This
alternate syntax of DEFINE-METHOD-COMBINATION is provided for convenience
and is recognized when the second subform is a non-null symbol. By
convention, name and operator are often the same symbol, but this is not
required.
This method-combination type recognizes unqualified methods and methods
with one qualifier, the keyword symbol with the same name as name, as
primary methods. It also recognizes methods with one qualifier, :around,
as auxiliary methods that behave the same as :around methods in standard
method combination.
A method-combination type defined this way always takes one optional
argument, order, defaulting to :most-specific-first. A value of
:most-specific-last reverses the order of the primary methods, without
affecting the order of the auxiliary methods.
The last example above is, in fact, an example of the macro expansion of
the short form expression (define-method-combination and and).
>>> ADVANCED FACILITIES:
These facilities could be included if we want a comprehensive standard, or
could be omitted for the time being if we prefer a stripped-down standard.
I've only included facilities whose usefulness has been demonstrated in
Flavors.
Keyword options for method-group specifiers in define-method-combination:
:ORDER -- the argument is a form evaluating to :MOST-SPECIFIC-FIRST or
:MOST-SPECIFIC-LAST. If it evaluates to any other value, the system issues
a warning. This is a convenience, to avoid having to write the CASE expression
seen in the last example above, and does not add any expressive power.
:DESCRIPTION -- the argument is a format-string used in (APPLY #'FORMAT
stream description (METHOD-QUALIFIERS method)). In most cases the
description will not contain any format directives. The description should
be concise (one or two words). If no description is specified, a default
description is chosen based on the variable name, the qualifier patterns,
and whether this method-group includes the unqualified methods. This
description mechanism tells programming environment tools the meaning of
method qualifiers.
Additional keyword arguments for MAKE-METHOD-CALL:
:ARGLIST list-of-forms
Uses the specified forms as the arguments to each method instead of
using the arguments to the generic function.
:APPLY list-of-forms
Same as :arglist except that the last form in the list evaluates to
a list of arguments and the call is made with apply rather than funcall.
You must not specify both :arglist and :apply.
This is a bit more complicated than it seems at first, because there are
three potentially different argument lists involved. (1) The arguments
supplied to the generic function. (2) The arguments passed from the
generic function to the methods. (3) The arguments actually received by a
method. (2) differs from (1) in certain proposals for discrimination on
optional arguments, such as the &generic-optional one and the :interface
one. (3) differs from (2) in implememtations that have a special calling
sequence for methods. The :arglist/:apply keywords for make-method-call
allow you to change the (2) arguments; any implementation-dependent
transformation from (2) to (3) still applies.
It is not a good idea to change arguments that are used for discrimination,
since this could cause a method to be called with an argument that does
not match its parameter specializer.
WITH-METHOD-ARGUMENT-ACCESSORS lambda-list &body body [macro]
This macro is convenient when changing the arguments passed to the methods.
Each parameter in lambda-list is bound to a form that accesses the
corresponding method argument, and then body is executed. These accessor
forms come from the hidden information mentioned above. Lambda-list must
match the (2) arguments mentioned above.
∂05-Jan-87 1246 Gregor.pa@Xerox.COM Re: Question about MAKE-METHOD Arguments
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 12:45:20 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 12:42:50 PST
Date: 5 Jan 87 12:42 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Question about MAKE-METHOD Arguments
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 28 Dec 86
16:56 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870105-124250-3526@Xerox>
Date: 28 Dec 86 16:56 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
To Gregor:
When you state that the same ``method could be on (sic) more
than one generic function,'' does this preclude different method
objects sharing the same underlying method function? That is, would
it be ok to have the method object know the generic function it is
part of, but not the method function (which is the meat of the
method object)? Do you envision glueing method objects in a
variety of generic functions?
I believe that the method-function of a method should be a mutable slot.
Consequently, I imagine that multiple methods could have the same
function.
Methods could be added to a variety of generic functions, but some
method-class, generic-function-class combinations will signal an error
because it will be inconsistent for that kind of method to be added to
that kind of generic function.
∂05-Jan-87 1326 Gregor.pa@Xerox.COM Re: Terminology: default value form
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 13:26:46 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 13:14:27 PST
Date: 5 Jan 87 13:14 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Terminology: default value form
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 31 Dec 86 00:50 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870105-131427-3572@Xerox>
Moon says:
"initial value form" rather than "default value form" is fine,
although I don't see why users would expect this system to behave
like LOOPS. It doesn't seem to have much resemblance to LOOPS.
One could argue that the word "default" here is justified because
this form only provides the initial value if another initial value
is not specified by the caller of MAKE-INSTANCE. Thus it is the
DEFAULT initial value form.
Note that in the simplified initialization protocol I sent out, they are
INITIAL value forms. That is because they are always evaluated by
make-instance, and the slots are always set to their values.
Afterwards, the initialize generic-function is called on the instance
and the "init-plist".
The method on initialize for OBJECT, fills in slot values from the
init-plist, but some classes may override that method so they will not
get this behavior.
∂05-Jan-87 1326 Gregor.pa@Xerox.COM Re: MAKE-METHOD arguments discussion
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 13:26:39 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 13:06:16 PST
Date: 5 Jan 87 13:06 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: MAKE-METHOD arguments discussion
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Sun, 28 Dec 86 19:16 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870105-130616-3564@Xerox>
Moon says:
I forgot to mention that I don't see how the capability of
WITH-SLOTS to determine the class of an instance-form by looking at
the defmethod lambda-list can be implemented without blessing the
function. Or is that a feature that only works inside defmethod
and isn't available to users making their own methods at the
make-method level?
The reason I don't want the function to be blessed is that given this
situation:
(defclass foo () (x))
(defmethod foo ((f foo)) (slot-value f 'x))
I want it to be legal to say one of:
(funcall (get-method (symbol-function 'foo) () (list (class-named
'foo)))
(make-instance 'foo))
or:
(funcall (method-function
(get-method (symbol-function 'foo) () (list (class-named
'foo))))
(make-instance 'foo))
I want it to have the same effect as saying:
(foo (make-instance 'foo))
Danny's idea for communicating class informat to with-slots, (including
information which would allow optimizations), was to have method-lambda,
so:
(funcall #'(method-lambda ((f foo)) (with (f) x))
(make-instance 'foo 'x 1))
would return 1, but
(funcall #'(method-lambda ((f foo)) (with (f) x))
nil)
is an error
∂05-Jan-87 1351 Gregor.pa@Xerox.COM Re: Comments on various comments
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 13:51:33 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 13:41:00 PST
Date: 5 Jan 87 13:39 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Comments on various comments
In-reply-to: Masinter.pa's message of 30 Dec 86 10:52 PST
To: Masinter.pa@Xerox.COM
cc: Bobrow.pa@Xerox.COM, Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870105-134100-3629@Xerox>
Larry says:
c) (masinter) top of hierarchy is CLASS, GENERIC-FUNCTION,
METHOD, with the names of the default ones unspecified, some
implementations can in fact use CLASS, GENERIC-FUNCTION,
METHOD and shadow any unwanted behavior in the subclasses.
In another message, which I can't find, he says something like:
A defclass which defined a class with no slots might create a class
was an instance of no-slots-class or something.
I see, I had missed an important point, which is that defclass,
defmethod and friends might not always want to create the same kind of
class. We might want to give them flexibility to do that.
The problem is that we would definitely like people to be able to do
"programmatically" what defclass, defmethod and friends do. So that
SOMETHING LIKE:
(setf (class-named 'foo)
(make-instance 'default-class :name 'foo))
would be the same as:
(defclass foo () ())
I think the easiest way to provide that ability is to specify that
defclass must produce a class of class standard-class, and as I
suggested before (although not with the reference to this message) we
use alternative b.
b) (moon) top of hierarchy is CLASS, GENERIC-FUNCTION, METHOD,
with the default ones named STANDARD-CLASS,
STANDARD-GENERIC-FUNCTION, STANDARD-METHOD
∂05-Jan-87 1359 Gregor.pa@Xerox.COM Re: STANDARD-TYPE-CLASS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 13:58:15 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 13:54:07 PST
Date: 5 Jan 87 13:54 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: STANDARD-TYPE-CLASS
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 31 Dec 86
15:14 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870105-135407-3657@Xerox>
I think that the concept of built-in-class and standard-type-class as
defined by Dick are important and make sense. I think these should be
mixin's though since there are several possible reasonable combinations.
Something like the following seems right:
(defclass class () ()) ;the top
(defclass built-in-class-mixin (class) ()) ;microcode knows about
these
(defclass standard-type-class-mixin (class) ()) ;Steele knows about
these
(defclass standard-class (class) ()) ;defclass makes these
;;;
;;; Important combinations of the above:
;;;
(defclass standard-extensible-class (class standard-type-class-mixin)
())
(defclass standard-built-in-class (built-in-class-mixin
standard-type-class-mixin)
())
The following are values that MANY, but not all implementations would
return.
(class-of (class-named 'pathname)) ==> standard-extensible-class
(class-of (class-named 'cons)) ==> standard-built-in-class
(class-of (class-named 'stream)) ==> standard-class-mixin
These say that:
PATHNAME is a standard class defined by Steele, in addition, it can be
specified as a direct-superclass in a defclass form.
FIXNUM is a standard class defined by Steele. In addition, it is
represented "fundamentally" by this Lisp.
STREAM is a standard class defined by Steele. It is not represented
fundamentally by this Lisp, but it may not be included as a direct
superclass in a defclass form.
∂05-Jan-87 2034 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: MAKE-METHOD arguments discussion
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 5 Jan 87 20:33:26 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 36257; Mon 5-Jan-87 23:32:55 EST
Date: Mon, 5 Jan 87 23:31 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: MAKE-METHOD arguments discussion
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870105-130616-3564@Xerox>
Message-ID: <870105233151.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 5 Jan 87 13:06 PST
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Moon says:
I forgot to mention that I don't see how the capability of
WITH-SLOTS to determine the class of an instance-form by looking at
the defmethod lambda-list can be implemented without blessing the
function. Or is that a feature that only works inside defmethod
and isn't available to users making their own methods at the
make-method level?
The reason I don't want the function to be blessed is that given this
situation:
(defclass foo () (x))
(defmethod foo ((f foo)) (slot-value f 'x))
I want it to be legal to say one of:
(funcall (get-method (symbol-function 'foo) () (list (class-named
'foo)))
(make-instance 'foo))
or:
(funcall (method-function
(get-method (symbol-function 'foo) () (list (class-named
'foo))))
(make-instance 'foo))
I want it to have the same effect as saying:
(foo (make-instance 'foo))
Oh, gross! What is the reason for wanting this?
Danny's idea for communicating class informat to with-slots, (including
information which would allow optimizations), was to have method-lambda,
so:
(funcall #'(method-lambda ((f foo)) (with (f) x))
(make-instance 'foo 'x 1))
would return 1, but
(funcall #'(method-lambda ((f foo)) (with (f) x))
nil)
is an error
Sure, but doesn't using method-lambda constitute blessing the function?
∂05-Jan-87 2129 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: :allocation slot-option issues
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 5 Jan 87 21:29:30 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 36285; Tue 6-Jan-87 00:28:25 EST
Date: Tue, 6 Jan 87 00:27 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: :allocation slot-option issues
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870105-110752-3299@Xerox>
Message-ID: <870106002722.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 5 Jan 87 11:07 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
....Specification of Inheritance
None of :reader :accessor :allocation or :initialize-only (if we still
have that) are inherited....
We decided at the meeting in Menlo Park that :reader and :accessor
are inherited. It is difficult to see how it could be otherwise if
they are defined in terms of defmethod.
Comments on the rest of your message to follow at some later date.
∂05-Jan-87 2154 Moon@STONY-BROOK.SCRC.Symbolics.COM Class Precedence List
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 5 Jan 87 21:54:44 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 36292; Tue 6-Jan-87 00:54:17 EST
Date: Tue, 6 Jan 87 00:53 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Class Precedence List
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 3 Jan 87 01:31 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
References: <861122002029.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870106005305.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 02 Jan 87 2231 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
I've been searching for a way to explain the class precedence list
computation that is simpler than the existing explanations. I think we
can explain it fairly well if we relax, a bit, the requirements of
implementations, though we can certainly recommend that implementations go
the extra distance. What I'm proposing is a subset of the behavior that
the Moon algorithm has, but it is simple to explain and understand.
I'm not thrilled with any "standard" where it is legal for different
implementations to produce different results for the class precedence
list. That could lead to needlessly obscure portability problems.
(I think Dick changed his mind on this, judging by a later message, but
I'd like to get explicit confirmation in case I'm jumping to conclusions.)
....If D is a direct superclass of C, where C is in CL, then (C,D) is in the
partial order. If D1 and D2 are direct superclasses of C, where C is in
CL, such that D1 precedes D2 in the local precedence order, then
(D1,D2) is in the partial order. (Note, these correspond to Moon's rules 1
and 2, but we explicitly list the pairs of relations, and we deal with
direct superclasses only.)
These are identical to "my" rules 1 and 2. If you thought those rules
didn't apply to direct superclasses only, then you were misled by the
inconsistent terminology in the concepts document (or by applying one
terminology while reading a version of it that was written with a
different terminology).
Now we topologically sort the elements of CL. This is done as follows.
Select a class C that is not preceded by any other. Put it first in the order.
Remove C from CL and remove all pairs that mention it. This new CL is again
partially ordered by the new pairs. Select a C that is not preceded by
any other and put it next in the order. Continue until CL is empty.
This is a fairly good description of the Lisp code I mailed out some months
ago, except that it prefers treewalk order when it has a choice, rather than
making an arbitrary choice. I can mail it out again if you like.
If there are several total orders, the result of the topological sort depends
on the order that the algorithm selects classes that are not preceded by
any others. This depends, generally, on the order that the DEFCLASS's were
evaluated.
I propose that we require implementations to select a total order using an
implementation of topological sort, and that we encourage implementations
to signal an error when several total orders are possible.
The referenced message (sent 22 Nov 86) was a discussion of why this
(signal an error when several orders are possible) won't work. Until I
did that research I had thought it was a good idea.
I don't see any harm in mentioning the concept of topological sort in the
documentation of how the precedence list is computed, although when we were
writing the Flavors documentation we decided that it obscured more than it
clarified. Perhaps you feel the CLOS standards document is aimed at a more
mathematically sophisticated audience.
[from a later message from Dick]
I believe that this algorithm produces the same results as
the New Flavors algorithm, but it is easier to explain: 1. Compute the
partial order relations; 2. topologically sort; 3. when topological sort
has a choice of several classes to put next, select according to preorder.
That sounds identical to the so-called New Flavors algorithm to me. Is
this just an issue of the particular words used to describe it, or is
there something more going on that hasn't penetrated my head yet?
Danny: I may have missed your last message on the subject, since I only
remember messages containing algorithms that didn't work. Could you
send me a message reference or at least a date? (then I can retrieve
your message from one of the mailing list archives).
∂06-Jan-87 0141 Bobrow.pa@Xerox.COM Re: :allocation slot-option issues
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Jan 87 01:41:15 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 06 JAN 87 01:41:12 PST
Date: 6 Jan 87 01:40 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: :allocation slot-option issues
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 6 Jan 87 00:27 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870106-014113-4241@Xerox>
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Date: 5 Jan 87 11:07 PST From: Danny Bobrow
<Bobrow.pa@Xerox.COM>
....Specification of Inheritance
None of :reader :accessor :allocation or
:initialize-only (if we still have that) are inherited....
We decided at the meeting in Menlo Park that :reader and
:accessor are inherited. It is difficult to see how it could be
otherwise if they are defined in terms of defmethod.
Comments on the rest of your message to follow at some later
date.
Of course the methods generated by :reader and :accessor are inherited,
but not the features of the slot. That is
(defclass foo () ((x :initform 1 :reader foo-x)))
effectively generates
(demethod foo-x ((obj foo)) (slot-value obj 'x))
but
(defclass fie (foo) ((x :initform 2)))
does not generate
(defmethod foo-x ((obj fie)) (slot-value obj 'x))
although (foo-x (make-instance 'fie)) --> 2
∂06-Jan-87 0156 Bobrow.pa@Xerox.COM Re: Class Precedence List
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Jan 87 01:56:26 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 06 JAN 87 01:56:43 PST
Date: 6 Jan 87 01:56 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Class Precedence List
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 6 Jan 87 00:53 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870106-015643-4258@Xerox>
The following is my message (slightly edited to emphasize the difference
from an earlier (buggy) message), and the code Gregor and I produced for
class precedence list.
Date: 1 Dec 86 18:50 PST
Sender: Bobrow.pa
Subject: Re: Class precedence list
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
Message-ID: <861201-185029-2210@Xerox>
To restate the rules I think are appropriate, they are (slightly edited
from my message of 20 October):
The class precedence list is a left to right, depth first linearization
of the transitive closure of inheritance from the local super classes of
a class. It satisfies three constraints:
C-1) A class appears only once on the list.
C-2) The order of classes in a local supers list is preserved
C-3) A class always precedes all classes in its local supers list
It can be thought of as constructed as follows:
1) Walk the inheritance tree in left to right depth
first order, recording all super classes in the order visited.
2) Remove duplicates, preserving the last occurrence
of any class. This can be combined with step 1
without extra consing. This ensures that C-1 is satisfied.
In most cases C-2 and C-3 will also be satisfied.
This is true for all the examples in the Concepts document.
3) Traverse the resulting list from left to right. If
for any class c1, there is a class to its right that c1 should
follow, move c1 to the right of the rightmost such class.
This rightmost class must be computed by recursive application
of
rules C-2 and C-3. (*** This recursive dependency is the
difference between my earlier set of rules that Moon
found buggy, and this set)
In computing this recursive dependency, a dependency loop may be
discovered, indicating an error.
This algorithm gives a well defined order in which all internal
superclasses of class-1 will precede all internal superclasses of
class-2 if there is no intersection. (*** This does provide a
topological sort of the type specified by RPG, with a preferred total
order based on the tree walk)
Examples:
No intersection
(DEFCLASS1 C1 ())
(DEFCLASS1 C2 ())
(DEFCLASS1 D1 (C1))
(DEFCLASS1 D2 (C2))
(DEFCLASS1 E1 (D1 D2))
After Steps 1 and 2
(E1 D1 C1 D2 C2)
Simple Intersection:
(DEFCLASS1 C1 (OBJECT))
(DEFCLASS1 C2 (OBJECT))
(DEFCLASS1 D1 (C1))
(DEFCLASS1 D2 (C2))
(DEFCLASS1 E1 (D1 D2))
After Steps 1 and 2
(E1 D1 C1 D2 C2 OBJECT)
Moving Required:
(DEFCLASS1 C1 ())
(DEFCLASS1 C2 ())
(DEFCLASS1 C3 ())
(DEFCLASS1 D1 (C1 C2))
(DEFCLASS1 D2 (C1 C3))
(DEFCLASS1 E1 (D1 D2))
After Steps 1 and 2
(E1 D1 C2 D2 C1 C3)
In step 3, C2 must be moved after C1.
resulting in
(E1 D1 D2 C1 C2 C3)
Simple Error:
(DEFCLASS1 C2 ())
(DEFCLASS1 C3 ())
(DEFCLASS1 D4 (C3 C2))
(DEFCLASS1 D5 (C2))
(DEFCLASS1 D6 (C3 C2 D5 D4))
After steps 1 and 2:
(D6 D5 D4 C3 C2)
Now D5 needs to after C2 from D6 definition. Computing the recursive
closure of the constraints on D5, we see that C2 must be after D4 from
D4, and D4 must be after D5 from D6!!! Error.
Complex Constraint
(DEFCLASS1 E1 (C1))
(DEFCLASS1 E2 (C2))
(DEFCLASS1 E3 (C3))
(DEFCLASS1 E4 (E3 E2 E1))
(DEFCLASS1 E5 (C1 C2))
(DEFCLASS1 E6 (C2 C3))
(DEFCLASS1 E7 (E5 E6 E4))
After Steps 1 and 2
(E7 E5 E6 E4 E3 C3 E2 C2 E1 C1)
In Step 3
C3 has to be after C2 from E6, and hence after C1 from E5, giving
(E7 E5 E6 E4 E3 E2 C2 E1 C1 C3)
Now C2 is next in the list and it moves past C1 from E5, giving
(E7 E5 E6 E4 E3 E2 E1 C1 C2 C3).
Date: Tue, 2 Dec 86 16:11 PST
From: Gregor.pa
Subject: code for compute-class-precedence-list
To: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <861202161119.4.GREGOR@AVALON.isl.parc.xerox.com>
Line-fold: no
Here is the code and some examples for the latest version of
compute-class-precedence-list as described by Danny yesterday.
At the end are some examples.
(DEFMACRO DEFCLASS1 (NAME SUPERCLASSES)
`(progn (setf (get ',name 'supers) ',superclasses)))
(defun compute-class-precedence-list (root)
(let ((cpl ())
(must-precede-alist ()))
;; We start by computing two values.
;; CPL
;; The depth-first left-to-right up to joins walk of the supers
tree.
;; MUST-PRECEDE-ALIST
;; An alist of the must-precede relations. The car of each
element of the
;;; must-precede-alist is a class, the cdr is all the classes
which must
;; precede that class in the CPL.
;;
;; Note that the actual walk is breadth-first, right-to-left.
;;
(labels ((walk-supers (class &optional precedence)
(let ((elem (assoc class must-precede-alist)))
(if elem
(setf (cdr elem) (union (cdr elem) precedence))
(push (cons class precedence) must-precede-alist)))
(let* ((rsupers (reverse (cons class (get class 'supers))))
(precedence (cdr rsupers)))
(do ((sup rsupers (cdr sup))
(pre precedence (cdr pre)))
((null pre))
(walk-supers (car sup) pre)))
(unless (member class cpl) (push class cpl)))
(must-move-p (element list &aux move)
(dolist (must-precede (cdr (assoc element must-precede-alist)))
(when (setq move (member must-precede (cdr list)))
(return move))))
(find-farthest-move (element move)
(let ((closure (compute-must-precedes-closure element)))
(dolist (must-precede closure)
(setq move (or (member must-precede move) move)))
move))
(compute-must-precedes-closure (class)
(let ((closure ()))
(labels ((walk (element path)
(when (member element path)
(class-ordering-error
root element path must-precede-alist))
(dolist (precede (cdr (assoc element must-precede-alist)))
(pushnew precede closure)
(walk precede (cons element path)))))
(walk class nil)
closure))))
(walk-supers root) ;Do the walk
;; For each class in the cpl, make sure that there are no classes
after it which
;; should be before it. We do this by cdring down the list,
making sure that for
;; each element of the list, none of its must-precedes come after
it in the list.
;; If we find one, we use the transitive closure of the
must-precedes (using
;; find-farthest-move) to see where the class must really be
moved. We use a
;; hand-coded loop so that we can splice things in and out of the
CPL as we go.
(let ((tail cpl)
(element nil)
(move nil))
(loop (when (null tail) (return))
(setq element (car tail)
move (must-move-p element tail))
(cond (move
(setq move (find-farthest-move element move))
(setf (cdr move) (cons element (cdr move)))
(setf (car tail) (cadr tail));OK to use Interlisp delete trick
since it
(setf (cdr tail) (cddr tail));will never be the last element of
the list.
)
(t
(setq tail (cdr tail)))))
(copy-list cpl)))))
(defun class-ordering-error (root element path must-precede-alist)
(declare (ignore root))
(setq path (cons element (reverse (member element (reverse path)))))
(let ((explanations ()))
(do ((tail path (cdr tail)))
((null (cdr tail)))
(let ((after (cadr tail))
(before (car tail)))
(if (member after (get before 'supers))
(push (format nil "~% ~A must precede ~A -- ~A is in the local
supers of ~A."
before after after before)
explanations)
(dolist (common-precede (intersection
(cdr (assoc after must-precede-alist))
(cdr (assoc before must-precede-alist))))
(when (member after (member before (get common-precede 'supers)))
(push (format nil "~% ~A must precede ~A -- ~A has local supers ~S."
before after
common-precede
(get common-precede 'supers))
explanations))))))
(error "While computing the class-precedence-list for the class
~A:~%~
There is a circular constraint through the classes:~{
~A~}.~%~
This arises because:~{~A~}"
root path (reverse explanations))))
;;;; Examples
(defclass1 o ())
(defclass1 b1 (o))
(defclass1 b2 (o))
(defclass1 b3 (o))
(defclass1 b4 (o))
(defclass1 ex1-1 (b1 b3 b4))
(defclass1 ex1-2 (b2 b3))
(defclass1 example-1 (ex1-1 ex1-2))
(equal (compute-class-precedence-list 'example-1)
'(EXAMPLE-1 EX1-1 B1 EX1-2 B2 B3 B4 O))
(defclass1 o ())
(defclass1 b1 (o))
(defclass1 b2 (o))
(defclass1 b3 (o))
(defclass1 ex2-1 (b1))
(defclass1 ex2-2 (b2))
(defclass1 ex2-3 (b3))
(defclass1 example-2 (ex2-1 ex2-2 ex2-3))
(equal (compute-class-precedence-list 'example-2)
'(EXAMPLE-2 EX2-1 b1 EX2-2 b2 EX2-3 b3 O))
(DEFCLASS1 C1 ())
(DEFCLASS1 C2 ())
(DEFCLASS1 C3 ())
(DEFCLASS1 C4 (C1 C2))
(DEFCLASS1 C5 (C3 C2))
(DEFCLASS1 C6 (C4 C5))
(equal (compute-class-precedence-list 'c6)
'(C6 C4 C1 C5 C3 C2))
(DEFCLASS1 E1 (c1))
(DEFCLASS1 E2 (c2))
(DEFCLASS1 E3 (c3))
(DEFCLASS1 E4 (E3 E2 E1))
(DEFCLASS1 E5 (c1 c2))
(DEFCLASS1 E6 (c2 c3))
(DEFCLASS1 E7 (E5 E6 E4))
(equal (compute-class-precedence-list 'e7)
'(e7 e5 e6 e4 e3 e2 e1 c1 c2 c3))
(defclass1 d0 ())
(defclass1 d1 ())
(defclass1 d2 ())
(defclass1 d3 ())
(defclass1 e (d0 d1))
(defclass1 f (d1 d2 d3))
(defclass1 g (d1 d2))
(defclass1 h (d0))
(defclass1 foo (e f g h))
(equal (compute-class-precedence-list 'foo)
'(foo e f g h d0 d1 d2 d3))
(DEFCLASS1 D1 ())
(DEFCLASS1 D2 ())
(DEFCLASS1 D3 ())
(DEFCLASS1 D4 (D3 D2))
(DEFCLASS1 D5 (D2))
(DEFCLASS1 D6 (D3 D2 D5 D4))
(COMPUTE-CLASS-PRECEDENCE-LIST 'D6) ;should error
(defclass1 g1 ())
(defclass1 g2 ())
(defclass1 g3 ())
(defclass1 g4 ())
(defclass1 g5 (g1 g2))
(defclass1 g6 (g2 g3))
(defclass1 g7 (g3 g4))
(defclass1 g8 (g4 g5 g6 g7))
(compute-class-precedence-list 'g8) ;should error
∂06-Jan-87 0250 Bobrow.pa@Xerox.COM Re: Method Combination Proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Jan 87 02:49:54 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 06 JAN 87 02:44:33 PST
Date: 6 Jan 87 02:44 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Method Combination Proposal
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 5 Jan 87 15:34 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870106-024433-4277@Xerox>
Moon says:
Looking back over the old discussion, the motivation for the
find-methods scheme was stated to be simplicity, but in each
version it gets more and more complicated. I don't think it really
achieves its goal. Allow me to offer a few other criticisms,
briefly: The :qualifier-set option duplicates the information in
the arguments to find-methods, with a different syntax, and with a
different expressive power (unless one resorts to the escape to a
predicate function).
But it is the escape that I expect to use, say, for allowing one to
specify for example, that a qualifier is a real (realp) where one uses
the numeric value to order the methods. Or to specify a qualifier is
any single symbol used as a name.
; this duplicate information will be highly error-prone.
One answer is to add a new possible value, :explicit, for
:qualifier-set. In this case, all explicit calls to find-method will
be examined to determine allowable methods.
The :qualifier-set syntax doesn't seem to allow a way
to say anything about unqualified methods and doesn't seem to have
the flexibility to deal with methods with more than one qualifier.
The examples are hard to understand since the :qualifier-set syntax
used in the :and example is not the same as the syntax described
earlier, and because the backquotes and commas are messed up.
I would be willing to look further at the language for :qualifier-set.
It was there to answer the stated needs for environment information, and
I didn't give it enough thought.
Moon says:
The first part defines the meaning of the method qualifiers,
while the second part defines how the methods are glued together.
It's important that the definition of the method qualifiers is all
in one place, and I think it's important not to mix it up with
other stuff.
The question is whether it is there at point of use. Why isn't it
better to separate out environmental and programmatic concerns?
A survey of Symbolics object-oriented code shows that the form
of standard method combination with the primary methods in
most-specific-last order is not needed, so the standard method
combination does not need to take any arguments (another
simplification relative to my earlier proposals). The same survey
showed that most-specific-last order is quite useful with some
kinds of method combination that invoke all the methods (rather
than shadowing), specifically progn, list, append, and, and or
(this list is in decreasing order of popularity). The survey also
uncovered a user-defined method combination type that takes &key
arguments, hence my proposal still includes arguments in the
:METHOD-COMBINATION option to DEFGENERIC-OPTIONS
You do not show this one example, and I strongly prefer not having
arguments for this form.
A list of method-group specifiers follows.
I assume by this you mean the item noted by:
({(variable {qualifier-pattern}+ {keyword argument}*)}*)
Are the qualifier-patterns all lists or NIL, and hence distinguished
from the keywords? The :ORDER keyword seems weak at best.
I don't see any way to specify to the environment that any single symbol
would be an appropriate qualifier, or that a realp was OK.
Declarations at the head of the body are positioned directly
inside of bindings created by the lambda-list, and outside of the
bindings of the method-group variables.
I don't understand this. What does the declaration effect -- the
computation of the effective method form, or the compilation of that
form itself.
If a doc-string is present, it documents the method-combination
type.
Is this how we are going to do documentation. Must we always provide
such strings? Didn't someone else complain about this.
If I had to rank my objections, my strongest one is against the lambda
list.
Next is the restrictive nature of the qualifier language (I think the
escape to a predicate is crucial).
Finally, is the imposition of the idiom of putting the selection of
methods up front. I could live with this if the selection language (or
at least the test for qualifiers) could be made stronger. How about
making that form be
(variable find-method-filter &key :description :order)?
Somehow MAKE-METHOD-FROM-FORM got lost. Isn't it needed in
method-combination standard around the multiple-value-prog2 form?
around is a list of methods, and the multiple-value-prog2 form is not.
∂06-Jan-87 0822 Dussud%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Some invariants
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 6 Jan 87 08:22:26 PST
Received: from ti-csl by csnet-relay.csnet id ac01368; 6 Jan 87 10:22 EST
Received: from Jenner (jenner.ARPA) by tilde id AA09984; Tue, 6 Jan 87 08:56:52 cst
To: Danny Bobrow <Bobrow.pa@XEROX.COM>
Cc: Common-Lisp-Object-System@SU-AI.ARPA, Bobrow.pa@XEROX.COM
Subject: Re: Some invariants
Date: 6-Jan-87 07:51:45
From: Dussud%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <Dussud.2745928300@Jenner>
Here are some possible invariants and some arguments against them.
Which ones do you like?
(class-of (make-instance x)) = x
The class of the result of a make-instance is always the same as its
argument. A make-instance message could make a more specialized version
of itself, say as an environmental feature.
(not (eq (make-instance x) (make-instance x)))
This could usefully not be true if one of the initialization parameters
was a unique identifier (UID) that was supposed to identify the object
being created, and it already existed. Then the result of make-instance
should be the already existing object.
The arguments you give against those invariants make me think they would be true
only for the default class metaclass. Thus they shouldn't be stressed too much.
(eq (class-name (class-named x)) x)
This seems like it should be true, unless we make it such that classes
do not know their names, and the same class can have more than one name.
Is this useful? We could of course have a "hint" of a name in the class
for debugging purposes. This would make classes be first class
anonymous things as well.
I don't remember seeing CLASS-NAMED anywhere in the document, I might be wrong though.
Patrick.
∂06-Jan-87 1123 Moon@RIVERSIDE.SCRC.Symbolics.COM Re: :allocation slot-option issues
Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 6 Jan 87 11:18:49 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 90586; Tue 6-Jan-87 14:03:01 EST
Date: Tue, 6 Jan 87 14:00 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: :allocation slot-option issues
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870106-014113-4241@Xerox>
Message-ID: <870106140016.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 6 Jan 87 01:40 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Date: 5 Jan 87 11:07 PST
From: Danny Bobrow
....Specification of Inheritance
None of :reader :accessor :allocation or
:initialize-only (if we still have that) are inherited....
We decided at the meeting in Menlo Park that :reader and
:accessor are inherited. It is difficult to see how it could be
otherwise if they are defined in terms of defmethod.
Of course the methods generated by :reader and :accessor are inherited,
but not the features of the slot.
I see, ok. If text resulting from this conversation ends up in the document,
it will have to be worded more clearly, since it's easy to interpret ":reader
is not inherited" as ":reader has no effect on an inheriting class".
Comments on the rest of your message to follow at some later date.
∂06-Jan-87 1435 Gregor.pa@Xerox.COM Re: MAKE-METHOD arguments discussion
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Jan 87 14:35:29 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 06 JAN 87 14:31:52 PST
Date: 6 Jan 87 14:31 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: MAKE-METHOD arguments discussion
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 5 Jan 87 23:31 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870106-143152-4916@Xerox>
Date: Mon, 5 Jan 87 23:31 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Oh, gross! What is the reason for wanting this?
Let's not start this again. I don't think this is gross. In fact, I
think it would be gross not to do it this way. The point is, that with
meta-objects, it is more natural than before for the user to write code
which grovels around in the data-structure of the object system (the
meta-objects). In this kind of code, it is perfectly natural to want to
invoke a method's function.
I think it is bad modularity to push whatever slot access optimization
implementations may want to do into the user's face, by tacking extra
arguments onto method functions where the user can see them.
Specifically, I think the way this is done in flavors (with
self-mapping-table as the first argument) is bad modularity, because the
user should be allowed to think that when they type:
(defmethod foo ((arg0 class) arg1 arg2)
(equal (si:all-args-to-this-function) (list arg0 arg1 arg2)))
foo will return t.
Of course this particular piece of code is not such a good example, and
any example will not be portable, by my point remains valid --
implementations should hide implementation details from the user.
Sure, but doesn't using method-lambda constitute blessing the
function?
Yes and No. Yes, in that I don't really think method lambda is
necessary, and I am not a big fan of it. No in that I think
method-lambda is different than what I thought you meant by blessing the
function. Here are some examples which may illustrate the difference.
(flet ((make-method (specs function)
(make-instance 'default-method
'argument-specifiers (mapcar #'class-named
specs)
'function function)))
;; example-1
;; In this example, a previously compiled function is being used as
;; the method function of a method being added to foo.
;; This function does not expect to benefit from any optimizations
;; which might result if the compiler had known that its first
;; argument was going to be a rocket. All this function expects is
;; that it will receive one argument.
(add-method 'foo (make-method '(rocket) #'previously-compiled-fn))
;; example-2
;; In this example, a lambda expression is being used as the method
;; function of a method being added. The person who wrote this code
;; used method-lambda as a portable way of telling the compiler that
;; this function was going to be used as the method function of a
;; method with the argument specifiers as given in the method lambda.
;; Note that method-lambda does not authorize the compiler to change
;; the argument list of the lambda, the user must still be able to
;; get their hands on the method function and call it with one
argument,
;; all method-lambda authorizes the compiler to do is to compile the
;; lambda in such a way that it "is an error" to call it with an
argument
;; that is not a plane.
(add-method 'foo (make-method '(plane) #'(method-lambda ((p plane))
..)))
;; example-3
;; This is an example of what I think of as bad blessing. In this
;; example, like in example-1, the user had a previously compiled
;; function which does not need to or expect to benefit from having
;; the compiler know the class of its first argument. But, in order
;; to make the underlying implementation happy, the user must have
;; the function blessed, which may return a function with a different
;; argument list.
(add-method 'foo (make-method '(blanket) (bless-us
#'previously-compiled-fn))))
∂06-Jan-87 1900 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Method Combination Proposal
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 Jan 87 18:59:47 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 37316; Tue 6-Jan-87 21:59:04 EST
Date: Tue, 6 Jan 87 21:57 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Method Combination Proposal
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870106-024433-4277@Xerox>
Message-ID: <870106215759.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 6 Jan 87 02:44 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Moon says:
Looking back over the old discussion, the motivation for the
find-methods scheme was stated to be simplicity, but in each
version it gets more and more complicated. I don't think it really
achieves its goal. Allow me to offer a few other criticisms,
briefly: The :qualifier-set option duplicates the information in
the arguments to find-methods, with a different syntax, and with a
different expressive power (unless one resorts to the escape to a
predicate function).
But it is the escape that I expect to use, say, for allowing one to
specify for example, that a qualifier is a real (realp) where one uses
the numeric value to order the methods. Or to specify a qualifier is
any single symbol used as a name.
I had assumed this would be done in Lisp instead of a special embedded
language. See example below.
; this duplicate information will be highly error-prone.
One answer is to add a new possible value, :explicit, for
:qualifier-set. In this case, all explicit calls to find-method will
be examined to determine allowable methods.
To me this seems even more complicated.
The :qualifier-set syntax doesn't seem to allow a way
to say anything about unqualified methods and doesn't seem to have
the flexibility to deal with methods with more than one qualifier.
The examples are hard to understand since the :qualifier-set syntax
used in the :and example is not the same as the syntax described
earlier, and because the backquotes and commas are messed up.
I would be willing to look further at the language for :qualifier-set.
It was there to answer the stated needs for environment information, and
I didn't give it enough thought.
I don't understand this reference to environment information. I have
never proposed any special programming environment facilities here,
other than the :description thing to control printed representation.
You're probably referring to my insistence that macros that don't check
their arguments, but just ignore anything they don't recognize, are bad;
I think this is a language issue, not an environment issue. Bringing that
general point to the specifics of define-method-combination, I feel it's
important for a method-combination function to complain if there are
applicable methods that it doesn't support, rather than just ignoring
them. I'm not proposing that there be a warning at defmethod time, or
that a smart editor tell you when you enter the function; those things
might be useful, but they really are programming environment issues and
probably not appropriate for the object-oriented programming standard.
I'm just saying the method-combination function should complain at the
time it is called (which could be run-time, when the generic function
is called, but is likely to be earlier in most implementations).
If I was going to do those programming environment facilities, I would try
to do them by calling the method-combination function and seeing what
happens, rather than by adding a new syntax to be used in the
define-method-combination specifically to convey that information. This
is similar to the suggestion that the best way to find out what methods
are actually called is to call the method-combination function and
analyze the Lisp form it returns, rather than adding a new syntax for it
to return a list of methods.
Implementing this would require the condition system (another proposed
CL extension), or some other way to get control when the
method-combination function calls WARN. (Perhaps this is a good
argument for putting back the METHOD-COMBINATION-ERROR function, which
my recent proposal said was unnecessary? But I still think it's better
to call it WARN and let the programming environment use FLET to make it
different from the regular WARN if it needs to.)
Here's an example (promised above), showing how I would write a method
combination function that requires the qualifiers to be positive integers
and uses the qualifiers to control the order:
(define-method-combination example-method-combination ()
((methods (*))) ;all methods with exactly one qualifier
(dolist (method methods)
(unless (typep (first (method-qualifiers method)) '(integer 0 *))
(warn "Qualifier ~S of method ~S is not a positive integer"
(first (method-qualifiers method)) method)
(setq methods (delete method methods))))
(make-method-call (stable-sort methods #'<
:key #'(lambda (method)
(first (method-qualifiers method))))))
I hope this example clarifies what I'm talking about now. All the
special processing is in Lisp, not in an embedded language. Indeed,
this loses some declarative expressiveness, and I can't really claim
that the definition of the meaning of the method qualifiers is contained
entirely, or even mostly, in the second line of the definition.
However, I think it makes sense for the declarative form only to deal
with the easy cases, and leave the complicated cases to imperative Lisp
code. The switchover seems to be natural enough.
If you ask why have the declarative form at all, all proposals seem to agree
(tacitly?) that simple pattern-matching against symbols is the most common
case and is too verbose to write in Common Lisp.
Moon says:
The first part defines the meaning of the method qualifiers,
while the second part defines how the methods are glued together.
It's important that the definition of the method qualifiers is all
in one place, and I think it's important not to mix it up with
other stuff.
The question is whether it is there at point of use. Why isn't it
better to separate out environmental and programmatic concerns?
I hope the above makes this question moot.
A survey of Symbolics object-oriented code shows that the form
of standard method combination with the primary methods in
most-specific-last order is not needed, so the standard method
combination does not need to take any arguments (another
simplification relative to my earlier proposals). The same survey
showed that most-specific-last order is quite useful with some
kinds of method combination that invoke all the methods (rather
than shadowing), specifically progn, list, append, and, and or
(this list is in decreasing order of popularity). The survey also
uncovered a user-defined method combination type that takes &key
arguments, hence my proposal still includes arguments in the
:METHOD-COMBINATION option to DEFGENERIC-OPTIONS
You do not show this one example, and I strongly prefer not having
arguments for this form.
The details of the example really aren't relevant or interesting. I was
only interested in the fact that someone found &key arguments useful here.
What are your arguments against parameterizing method-combination schemas?
A list of method-group specifiers follows.
I assume by this you mean the item noted by:
({(variable {qualifier-pattern}+ {keyword argument}*)}*)
Yes. My English needs some cleaning up and clarification.
Are the qualifier-patterns all lists or NIL, and hence distinguished
from the keywords?
Possibly-empty lists or asterisks; this was in my message.
The :ORDER keyword seems weak at best.
Agreed; the message said it was only a convenience and relegated it to
the "advanced facilities" section, for things that could be excluded if
we wanted a lean proposal rather than a comprehensive one.
I don't see any way to specify to the environment that any single symbol
would be an appropriate qualifier, or that a realp was OK.
I hope the above example and discussion clarified this.
Declarations at the head of the body are positioned directly
inside of bindings created by the lambda-list, and outside of the
bindings of the method-group variables.
I don't understand this. What does the declaration effect -- the
computation of the effective method form, or the compilation of that
form itself.
The former, same as in DEFMACRO.
If a doc-string is present, it documents the method-combination
type.
Is this how we are going to do documentation. Must we always provide
such strings? Didn't someone else complain about this.
I've not a fan of doc-strings, but I think it's much more important to be
consistent with the rest of Common Lisp than to make diddly improvements
here. To my way of thinking, the syntax of DEFINE-METHOD-COMBINATION is
similar to the syntax of DEFMACRO and DEFSETF. By the way, Flavors'
DEFINE-METHOD-COMBINATION doesn't allow doc-strings.
If I had to rank my objections, my strongest one is against the lambda
list.
I'd like to understand why.
Next is the restrictive nature of the qualifier language (I think the
escape to a predicate is crucial).
I hope this is clarified now (read my next paragraph first). If not, we
need to keep discussing it.
Finally, is the imposition of the idiom of putting the selection of
methods up front. I could live with this if the selection language (or
at least the test for qualifiers) could be made stronger. How about
making that form be
(variable find-method-filter &key :description :order)?
I feel like I might have missed the point of this suggestion. Are you
saying that in place of the qualifier patterns one could put the name of a
predicate, in cases where the simple pattern match language wasn't strong
enough? That seems like a good idea. If you're suggesting adding a
hairier pattern match language, I don't go for that.
To make sure we understand each other, I'll rewrite the earlier example in
these terms:
(define-method-combination example-method-combination ()
((methods positive-integer-qualifier-p))
(make-method-call (stable-sort methods #'<
:key #'(lambda (method)
(first (method-qualifiers method))))))
(defun positive-integer-qualifier-p (method-qualifiers)
(and (= (list-length method-qualifiers) 1)
(typep (first method-qualifiers) '(integer 0 *))))
Thus the syntax of the third subform of define-method-combination
would be extended to
({ (variable {qualifier-pattern}+ {keyword argument}*)
| (variable predicate-symbol {keyword argument}*) }*)
Somehow MAKE-METHOD-FROM-FORM got lost. Isn't it needed in
method-combination standard around the multiple-value-prog2 form?
around is a list of methods, and the multiple-value-prog2 form is not.
My message said that MAKE-METHOD-FROM-FORM isn't needed. Instead
MAKE-METHOD-CALL is generalized to accept forms as well as methods.
By the way, I find the analogies between DEFINE-METHOD-COMBINATION and
DEFMACRO useful in several ways. Would it be a good idea to use that
analogy in the documentation?
∂07-Jan-87 1737 Gregor.pa@Xerox.COM Re: Method Combination Proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 7 Jan 87 17:36:54 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 07 JAN 87 17:24:19 PST
Date: 7 Jan 87 17:24 PST
Sender: Gregor.pa@Xerox.COM
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
Subject: Re: Method Combination Proposal
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 6 Jan 87 21:57 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
To: Bobrow.pa@Xerox.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870107-172419-6152@Xerox>
The most significant comment I have about this is that in both of your
proposals, you mention functions like MAKE-METHOD-CALL which can only be
called from the body of a define-method-combination. (Moon says this
explicitly, Danny just implies it).
This may be overly restrictive. I think that all of these functions
should take an extra argument (tentatively named the
method-combination-identifier) which would allow them to be called by
sub-functions of the particular method combination. The exisitence of
this "method combination identifier" interacts with the arguments to the
method combination since this identifier would have to be passed in
somehow, and the first argument to the method combination is a natural
place.
In addition, I think the body of the method combination should have
access to the generic function in question. It can't get it from the
methods since methods can be on more than one generic function.
So I could write
(define-method-combination mine (generic-function id)
((all (*)))
(grovel-my-method-combination generic-function id methods))
(defun grovel-my-method-combination (generic-function id methods)
..
(make-method-call id methods :operator 'foo)
..)
Note that even if we decide to restrict make-method-call to within the
body of define-method-combination I think the body should have access to
the generic function.
PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT. I don't see that this is an
appropriate mechanism for dealing with this optimization. It may just
be the name which is upsetting me, I am not sure yet.
:qualifier-set vs. * in pattern-language etc.
Moon's most recent message shows how defmethod can check the legality of
the qualifiers just by calling the method-combination and seeing if it
warns or errors. This is probably good enough, but it should be noted
that it lacks the kind of precision of error message which Danny's
:qualifier-set proposal had. On the other hand, the kind of tool which
could make use of that precision of error message definitely comes under
the environment category.
So I guess just using the template language will be good enough.
I also think the analogy between define-method-combination and defmacro
is useful, it would probably be worth including this analogy in the
spec.
∂07-Jan-87 1737 Masinter.pa@Xerox.COM Re: Some invariants
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 7 Jan 87 17:37:02 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 07 JAN 87 17:27:18 PST
Date: 7 Jan 87 17:28 PST
From: Masinter.pa@Xerox.COM
Subject: Re: Some invariants
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 5 Jan 87 11:29 PST
To: Bobrow.pa@Xerox.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870107-172718-6156@Xerox>
I like
(not (eq (make-instance x) (make-instance x)))
I believe that "make-" in general is expected to create a non-EQ
instance of a new object. The example you give (of looking up a name or
ID and either retrieving the old one or creating a new one should be
given a different name.
This is clearly a matter of preference (i.e., we don't have to restrict
make-instance for Classes to hang together), but the document we write
can and should impose stylistic conventions for what makes sense if the
user specializes built-in classes.
That make-instance always creates new structure is a very useful
property; for example, it means that
(let ((x (make-instance 'foo)))
(setf (foo-slot x) 3)
x)
has no global side effects.
∂07-Jan-87 1737 Masinter.pa@Xerox.COM Re: Some invariants
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 7 Jan 87 17:37:08 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 07 JAN 87 17:30:07 PST
Date: 7 Jan 87 17:31 PST
From: Masinter.pa@Xerox.COM
Subject: Re: Some invariants
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 5 Jan 87 11:29 PST
To: Bobrow.pa@Xerox.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870107-173007-6160@Xerox>
(class-of (make-instance x)) = x
is not as useful an invariant to protect. The weaker requirement, namely
(typep (make-instance x) x)
only implies (subtypep (class-of (make-instance x)) x).
∂07-Jan-87 1758 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Some invariants
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 7 Jan 87 17:58:21 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 38337; Wed 7-Jan-87 20:57:55 EST
Date: Wed, 7 Jan 87 20:56 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Some invariants
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870107-172718-6156@Xerox>
Message-ID: <870107205644.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 7 Jan 87 17:28 PST
From: Masinter.pa@Xerox.COM
That make-instance always creates new structure is a very useful
property; for example, it means that
(let ((x (make-instance 'foo)))
(setf (foo-slot x) 3)
x)
has no global side effects.
Not so. Someone might have done
(defmethod-setf foo-slot :before ((foo foo)) (new-value)
(push (list foo 'slot new-value) *mumble*))
Accessors are generic, and therefore can do anything.
∂07-Jan-87 1841 Masinter.pa@Xerox.COM Re: Some invariants
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 7 Jan 87 18:41:44 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 07 JAN 87 18:14:55 PST
Date: 7 Jan 87 18:16 PST
From: Masinter.pa@Xerox.COM
Subject: Re: Some invariants
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 7 Jan 87 20:56 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870107-181455-1005@Xerox>
I need to be more careful with my wording, since I clearly said it
wrong.
First, the issue here is not one of capability (what can you do) but of
style (what should you avoid doing).
Secondly, the phrase I used "has no global side effects" doesn't
describe what I meant, as David was quick to point out with a useful
example of global side effects when setting an accessor.
However, take the following program fragment:
(let ((x (make-instance 'foo))
(y (make-instance 'foo))
(setf (foo-slot x) 3)
(setf (foo-slot y) 4)
(foo-slot x))
It would be bad programming style for foo and its slot foo-slot to
behave in a way that this returned something other than 3 without
explicit documentation about this (fairly odd) behavior. Normally, one
would expect that each value returned by calls make-instance to be
independent of each other in this informal sense.
As long as this is a style recommendation rather than an implementation
requirement, expressing it as an "invariant" might be the wrong form of
expression.
Independent of the wording, do you agree with the sentiment?
∂07-Jan-87 1928 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Some invariants
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 7 Jan 87 19:27:58 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 38385; Wed 7-Jan-87 22:27:21 EST
Date: Wed, 7 Jan 87 22:26 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Some invariants
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870107-181455-1005@Xerox>
Message-ID: <870107222614.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 7 Jan 87 18:16 PST
From: Masinter.pa@Xerox.COM
(let ((x (make-instance 'foo))
(y (make-instance 'foo))
(setf (foo-slot x) 3)
(setf (foo-slot y) 4)
(foo-slot x))
It would be bad programming style for foo and its slot foo-slot to
behave in a way that this returned something other than 3 without
explicit documentation about this (fairly odd) behavior. Normally, one
would expect that each value returned by calls make-instance to be
independent of each other in this informal sense.
As long as this is a style recommendation rather than an implementation
requirement, expressing it as an "invariant" might be the wrong form of
expression.
Independent of the wording, do you agree with the sentiment?
I agree that a foo class that caused this program to return 4 would be
considered fairly odd and hard to understand. I certainly think it would
be wrong for the language to make it impossible to implement such a class;
I've had users plead with me that it was very important for them to be able
to do this (have make-instance do interning of one sort or another).
The style recommendation is fine, although it may be superfluous to put it
into the standards document.
∂07-Jan-87 2134 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Method Combination Proposal
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 7 Jan 87 21:34:20 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 38426; Thu 8-Jan-87 00:33:55 EST
Date: Thu, 8 Jan 87 00:32 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Method Combination Proposal
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870107-172419-6152@Xerox>
Message-ID: <870108003249.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Thanks for the comments. I hope to converge on this before the end of
the week.
Date: 7 Jan 87 17:24 PST
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
The most significant comment I have about this is that in both of your
proposals, you mention functions like MAKE-METHOD-CALL which can only be
called from the body of a define-method-combination. (Moon says this
explicitly, Danny just implies it).
This may be overly restrictive. I think that all of these functions
should take an extra argument (tentatively named the
method-combination-identifier) which would allow them to be called by
sub-functions of the particular method combination. The exisitence of
this "method combination identifier" interacts with the arguments to the
method combination since this identifier would have to be passed in
somehow, and the first argument to the method combination is a natural
place.
The problem is that this makes the normal case more verbose. From a user
point of view, the need for this "method combination identifier", which
the user can't do anything with other than to pass right back to the
system, doesn't seem very well motivated. As an implementor I can see
why it's needed, but to the user it's just the system sticking its
dirty laundry in his face. See below.
It may be worth clarifying what this auxiliary information consists of.
In Flavors, it is the arguments that the generic function will pass to
the effective-method; more precisely, it is the lambda-list of the
effective-method (called the combined-method in Flavors). This might be
the same as, or derived from, the lambda-list of the generic function,
but in various special cases it can be something else. The important
point is that this information is needed to fill in the arguments to
be passed to the method by the form returned by make-method-call.
That's what it is in the 3600 implementation of Flavors. I don't think
it is wise to constrain it to be exactly this in all implementations.
So I could write
(define-method-combination mine (generic-function id)
((methods (*)))
(grovel-my-method-combination generic-function id methods))
(defun grovel-my-method-combination (generic-function id methods)
..
(make-method-call id methods :operator 'foo)
..)
What I had in mind was
(define-method-combination mine ()
((methods (*)))
(grovel-my-method-combination #'make-method-call methods))
(defun grovel-my-method-combination (make-method-call methods)
..
(funcall #'make-method-call methods :operator 'foo)
..)
which makes the auxiliary-function case more verbose, but keeps the
simple case simple. How does this strike you?
There were three other possible ways to deal with it that I didn't
like as well when thinking about this last year, but perhaps you
would like them better. All of them allow make-method-call to
be a globally-defined function, rather than a FLET function; the
advantages of this are that the user doesn't have to pass a closure
to the auxiliary function, and it becomes easier to bypass the
define-method-combination level and go directly to the meta-object
level, directly defining the method that define-method-combination
would expand into.
One is to pass any auxiliary information in special variables. This
is how it is currently done in Flavors.
The second is to pass any auxiliary information in the method objects.
It's likely that the generic function suffices and any other auxiliary
information can be found in slots of the generic function.
(See next issue.)
Finally, there is the approach of saying that it's a bad idea for
make-method-call to depend on any auxiliary information. Instead, it
should produce a form that just encodes its arguments in some suitable
fashion. The caller of the method-combination function has to further
process the returned form to make it into real executable code, by
putting in the actual argument forms whose values are to be passed to
the methods. I see three ways to do this; enclosing it in a LAMBDA or a
LET that binds variables whose names are known to MAKE-METHOD-CALL;
enclosing it in a MACROLET that defines a macro whose name is known to
MAKE-METHOD-CALL; or code-walking. Flavors experience (we used to do it
this way) shows that this is slower (at compile time) if you have to do
this extra level of macro expansion, but I don't think it's really such
a big deal. I'm almost convinced now that this is the right approach.
In addition to MAKE-METHOD-CALL, there is WARN (or METHOD-COMBINATION-ERROR),
which also requires auxiliary information in some form. Removing this
auxiliary information seems more difficult; I don't see an analogy to
the "bad idea" approach above. Any ideas about that?
In any case, I agree that the issue of auxiliary functions called
by method-combination functions needs to be addressed one way or
another in the document; either by showing how it's done, or by
asserting that it isn't allowed.
---------------
In addition, I think the body of the method combination should have
access to the generic function in question. It can't get it from the
methods since methods can be on more than one generic function.
I don't think that has been agreed to. It seems to be simpler to allow
sharing of method-functions, but not sharing of method-objects.
I agree that there should be a way for the body of define-method-combination
to access the generic function. We have that in Flavors, but it was
removed in the evolution of the CLOS proposal. It can be put back.
---------------
PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT. I don't see that this is an
appropriate mechanism for dealing with this optimization. It may just
be the name which is upsetting me, I am not sure yet.
The other way to deal with this is to make it a keyword argument to
make-method-call, which defaults to (eq operator 'progn). I would be
happy with that; in fact I think it's what I proposed originally, but when
we discussed this in Menlo Park, the change to PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT
was made (I forget who proposed it and what the arguments were).
Note that the simple form of DEFINE-METHOD-COMBINATION would need this
keyword argument too.
---------------
:qualifier-set vs. * in pattern-language etc.
Moon's most recent message shows how defmethod can check the legality of
the qualifiers just by calling the method-combination and seeing if it
warns or errors. This is probably good enough, but it should be noted
that it lacks the kind of precision of error message which Danny's
:qualifier-set proposal had. On the other hand, the kind of tool which
could make use of that precision of error message definitely comes under
the environment category.
So I guess just using the template language will be good enough.
OK
---------------
I also think the analogy between define-method-combination and defmacro
is useful, it would probably be worth including this analogy in the
spec.
OK
∂08-Jan-87 1701 Moon@STONY-BROOK.SCRC.Symbolics.COM Lexical environment of slot default initial value forms
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 8 Jan 87 17:01:27 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 39397; Thu 8-Jan-87 20:01:01 EST
Date: Thu, 8 Jan 87 19:59 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Lexical environment of slot default initial value forms
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <870108195956.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
DLW points out that we should specify in what environment default
initial value forms for slots are evaluated, if/when they get evaluated.
This includes both the lexical environment and the dynamic environment.
Note that the lexical environment refers both to variables and to functions
(and to go tags, blocks, and declarations, if someone was so untasteful
as to do a non-local-go out of a default initial value form!); free variables
are rare in these forms, but free functions are common.
We discussed this and concluded that the lexical environment should be the
lexical environment where the form originally appeared, i.e. the lexical
environment in which defclass was evaluated, and the dynamic environment
should be the one in effect at the time the form is evaluated. There are
other suggestions, but they aren't as good. Happily, this is the same thing
that CLtL (p.309) says for defstruct slot initialization forms.
It can be difficult to get the correct lexical environment without any bugs
and simultaneously maximize efficiency, especially when using :constructor,
but I think it's more important for the language to have a clean definition.
If some implementations have bugs that's their business.
The good news is that most often these forms are constants, so the environments
don't matter. An implementation can optimize that case easily enough.
∂08-Jan-87 1714 RPG What's left to do
To: common-lisp-object-system@SAIL.STANFORD.EDU
For the March x3j13 meeting we have a number of things left to do.
1. Method combination. Moon is at work on this, so we are
likely in good shape.
2. Change-class. Discussion of this has stopped. Does this mean
we're settled?
3. Initialization protocol. Again, discussion has stopped: are we
agreed?
4. Class precedence list. I want to push my formulation of this. I'll
be sending a message later today on the topic. The latest CONCEPTS
file has a trial write-up of it.
-rpg-
∂08-Jan-87 1952 Moon@STONY-BROOK.SCRC.Symbolics.COM What's left to do
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 8 Jan 87 19:52:31 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 39467; Thu 8-Jan-87 22:51:56 EST
Date: Thu, 8 Jan 87 22:50 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: What's left to do
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 8 Jan 87 20:14 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870108225044.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 08 Jan 87 1714 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
For the March x3j13 meeting we have a number of things left to do.
It looks like you and I have both been worrying about the impending
deadline. Sonya and I have been putting together a list of issues
and my next message will be that list, as soon as I get it sorted into
priority order.
2. Change-class. Discussion of this has stopped. Does this mean
we're settled?
3. Initialization protocol. Again, discussion has stopped: are we
agreed?
I have not started on either of these. I'm trying to concentrate on one
issue at a time, which is why I haven't yet answered some of the mail on
these topics. I suspect we have a fair amount of work to do on 3.
∂08-Jan-87 2001 RPG Class Precedence List
To: common-lisp-object-system@SAIL.STANFORD.EDU
I am not necessarily trying to devise a new algorithm, but to duplicate
the current one in such a way that explaining how it works is easier. I
also have the goal of structuring the explanation so that the parts of the
algorithm that are important correspond to easily identifiable portions of
the explanation.
Here are the important parts of the algorithm, presented in increasing
order of importance:
1. We are embedding a partial order in a total order.
2. The important relations in the partial order are the lattice
order and the local precedence orders.
3. In case the lattice and local precedence orders underspecify the
total order, we use preorder treewalk order to specify it.
How does Dave's and Danny's explanations match up to these strictures?
Everyone's explanation states that a partial order is being embedded
in a total order.
Moon first:
Moon's first two rules state number 2 pretty well, but they leave
open the consideration of whether direct superclasses or superclasses
are meant by ``a class always precedes its own superclasses.'' This
doesn't matter, except that some reader might be slightly confused.
We, of course, can state the meaning exactly in the document.
Moon's rule 3 states:
``Duplicate classes are eliminated from the ordering; if a class
appears more than once, it is placed as close to the beginning of the
ordering as possible, while still obeying the other rules.''
What duplicates? Does this mean the user did
(defclass foo ...)
....
(defclass foo ...)
That's silly. But it is an interpretation that some reader might
pursue first.
There are two interpretations. One is that the rule that states that a
class always precedes its superclasses can introduce duplicates. Does this
mean that this rule is inconsistent? The other possibility is that a treewalk
is done from the class in question, call it C, to the top of the lattice, and
the resulting list contains duplicates. The rest of the explanation, which
is a description of a treewalk with insertions at the end of a list, seems
to hint at the second possibility.
The reader, puzzled, goes on to read the description of the treewalk process.
He thinks that the treewalk is the primary means of establishing the order, and
that the contraints in Moon's rules 1 and 2 sometimes change that order. Then
he has to understand that the treewalk might have to be repeated to add classes
left out. Why are they left out? Will this algorithm terminate?
Many intelligent readers will not believe that the predicate that tells
whether a class can be added at the end of the list being constructed can
be tested efficiently (one of Knuth's students wasn't sure; he believed the
algorithm did something reasonable after 15 minutes of study but could not
convince himself it could run efficiently.)
The impression that the treewalk is primay violates my third statement
that the lattice order and local precedence orders are the primary
determiners of the total order and the preorder is secondary.
Danny next.
Danny has three rules also. Rule 1 is:
C-1) A class appears only once on the list.
Hm. It couldn't be a total order is this weren't true. But extra
information is always ok, and we can make this part read well in
the document.
His rules 2 and 3 are simply the local precedence order and lattice
order rules, and well-stated.
Here is his explanation of what the class precedence list is. I
don't care about wording, but about what wrong impressions or
incomprehensibilities will rise in the reader's mind.
``The class precedence list is a left to right, depth first linearization
of the transitive closure of inheritance from the local super classes of
a class. It satisfies three constraints: <the three rules>''
The first sentence states that the class precedence list is a
linearization (total order) constructed by doing a preorder treewalk
and then making sure some constraints are followed.
Then he goes on to give an algorithm that does the preorder treewalk, putting
classes that appear several times as far to the right as possible. This
list is then edited using his rules 1, 2, and 3.
This algorithm gives primacy to the preorder treewalk, and there is a
question about whether the algorithm terminates - though it's actually
easy to prove if the algorithm is stated clearly - and about how the
error condition is computed.
In my formulation, Moon's rules 1 and 2 and Danny's rules 2 and 3
are explicit and refer to direct superclasses. Topological sort
is used because many people know it already, if they don't it's
easy to explain and to prove correct, and it emphasizes that the
local precedence order and lattice order are primary.
The topological sort algorithm clearly highlights where the two
problematic situations arise (loops and multiple orders), and it
is easy to see how the loop (inconsistency) error is noticed. When
multiple orders are possible, it shows up as a choice among a set of
classes. The condition can be noted and the preorder treewalk information
is appropriately applied here. The reader can see where this secondary
constraint enters the picture.
An explanation that depends on the mathematically known topological
sort lends some credibility that the concept of the class precedence
list and the algorithm for computing it are not ad hoc nightmares by
a group of crazed hackers.
Now, there is an interesting problem with the algorithm and explanation
that I gave, which is the situation with the example:
(defclass pie (apple cinnamon) ())
(defclass apple (fruit) ())
(defclass cinnamon (spice) ())
(defclass fruit () ())
(defclass spice () ())
EXAMPLE 1
This is one of Moon's examples. He states that his algorithm applied
to it produces an order, but that several other orders are possible.
The order his algorithm produces is:
(pie apple fruit cinnamon spice)
and the other two orders are:
(pie apple cinnamon fruit spice)
(pie apple cinnamon spice fruit)
On the other hand, the example
(defclass pie (apple cinnamon) ())
(defclass apple (fruit) ())
(defclass cinnamon (spice) ())
(defclass fruit (food) ())
(defclass spice (food) ())
(defclass food () ())
EXAMPLE 2
admits a single possibility by his rules, which is
(pie apple fruit cinnamon spice food)
Notice that the only difference between the two examples is that
the first is a true tree while the second is a lattice with a join
of FOOD.
If we insist that the class directed acyclic graph be a lattice, there
there is a least upper bound for every pair of classes, and the first
example has an implicit top element. In this case the first example
would admit the same result as the second. Here are pictures of
the situations:
EXAMPLE 1:
fruit spice
| |
| |
apple cinnamon
\ /
\ /
\ /
pie
Notice that fruit and spice have no join.
EXAMPLE 2:
food
/ \
/ \
fruit spice
| |
| |
apple cinnamon
\ /
\ /
\ /
pie
Here there is a join.
EXAMPLE 1':
T
/ \
/ \
fruit spice
| |
| |
apple cinnamon
\ /
\ /
\ /
pie
If there was a top element, call it the class named T, the first situation
would be this, which is the same as the original second situation (T is at
the top where FOOD would be). The original second situation would become
EXAMPLE 2':
T
|
food
/ \
/ \
fruit spice
| |
| |
apple cinnamon
\ /
\ /
\ /
pie
Without requiring that the class DAG be a lattice, my algorithm
always produces a total order when there is one, while Moon's
will produce the same one, but will admit several other possibilities.
When the class DAG is further restricted to being a lattice, Moon's
algorithm and mine agree (I think).
So, I propose that the class DAG should be required to be a lattice,
and because of that, I think, Moon's algorithm, Danny's, and mine are all
the same, and I think mine is the easiest to understand. I don't claim
superior skill at designing algorithms, because all I did was try to break
Moon's and Danny's algorithms down into the simplist terms.
I also propose that implementations be encouraged to offer a means of
warning or signalling an error every time that appeal is made to the
preorder.
-rpg-
∂08-Jan-87 2028 Moon@STONY-BROOK.SCRC.Symbolics.COM Issues for the CLOS committee to start focussing on
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 8 Jan 87 20:28:30 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 39486; Thu 8-Jan-87 23:26:44 EST
Date: Thu, 8 Jan 87 23:25 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Issues for the CLOS committee to start focussing on
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <870108232540.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
The following issues need to be resolved and documented by February 4
(to allow a document to be distributed before the March X3J13 meeting).
If we cannot resolve these among ourselves this month, we should put a
brief explanation of the open issues into the document. That way, the
document will accurately reflect our current status.
We only have three weeks, so let's try to focus on the important points
as much as possible and get some solid results down on paper.
>>> HIGH PRIORITY
Consistent terminology
- names for relationships among classes
- names for predefined classes & other interesting entities
- describing the terminology at the front of the document
- making sure the document adheres everywhere to the chosen terminology
(this may have been resolved already, but we were still discussing
it quite recently)
Initialization protocol.
(I have not yet started on this. I plan to think about it next week.)
Method-combination.
(I plan Friday to mail out complete documentation incorporating the
results of the recent discussion)
The class precedence rules, description, and algorithm. To a certain
extent these are three separate issues.
(Dick has been working on this, but I don't think it's resolved yet)
What happens when the partial order of class precedence admits more than
one total order.
(Currently the document says that it is recommended to signal an
error. I used to think that was a good idea, until I tried
implementing it and applying it to some real-life programs.
I reported on the results in a message of 22 Nov 86.
I firmly believe the order has to be well-defined, not
implementation-dependent, and cannot be considered an error.
Depth-first tree-walk order appears to be the correct disambiguator.)
We need to define quite explicitly the inheritance behavior of class
options and slot options. There should be a table listing each option
and showing how it inherits.
>>> LOWER PRIORITY
Structure of the classes for standard Common Lisp types. This means
which types have corresponding classes, and what the subclass and
precedence relations are.
(I thought this was resolved last year but the document doesn't
reflect that.)
Class redefinition and change-class protocol.
(I have not yet started on this)
Class variables.
(Discussion is ongoing, probably almost finished)
with-slots interning issue.
(Discussion is ongoing, probably almost finished)
Minor issues about which I sent mail as document comments, and
discussion doesn't seem to be continuing.
(Unless there are objections, I plan to proceed assuming
these are resolved, and update the documents accordingly.)
>>> LOWEST PRIORITY
Uninitialized slots (signal an error or return garbage?)
(Discussion is ongoing, probably almost finished)
Method lambda-list congruency rules.
(The document says these are a first approximation. This issue is
almost finished, but the rules for keywords might be wrong.)
MAKE-CLASS, REMOVE-CLASS.
(nothing in the document)
Some of the functions in the Functions chapter don't make sense
without the rest of meta-objects. Perhaps it should be reorganized
into two chapters.
:interface and :method-arguments options to defgeneric-options.
(These are currently out, but might go back in
once method-combination is fully clarified.)
∂08-Jan-87 2057 Dussud%Jenner%ti-csl.csnet@RELAY.CS.NET Re: MAKE-METHOD arguments discussion
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 8 Jan 87 20:57:05 PST
Received: from ti-csl by csnet-relay.csnet id ae03288; 8 Jan 87 23:51 EST
Received: from Jenner (jenner.ARPA) by tilde id AA00349; Thu, 8 Jan 87 17:13:23 cst
To: Gregor Kiczales <Gregor.pa@XEROX.COM>
Cc: Moon@SCRC-STONY-BROOK.ARPA, Common-Lisp-Object-System@SU-AI.ARPA
Subject: Re: MAKE-METHOD arguments discussion
Date: 8-Jan-87 16:06:03
From: Dussud%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <Dussud.2746130760@Jenner>
From Moon:
Oh, gross! What is the reason for wanting this?
From Gregor:
Let's not start this again. I don't think this is gross. In fact, I
think it would be gross not to do it this way. The point is, that with
meta-objects, it is more natural than before for the user to write code
which grovels around in the data-structure of the object system (the
meta-objects). In this kind of code, it is perfectly natural to want to
invoke a method's function.
I think we must start this again.
The real point is: How much of low level stuff do we want to expose?
The specification of the underlying metaclass protocol depends on the answer to
this question.
I think we want to expose enough so people can develop some new object oriented
paradigms without having to reimplement everything and being able to achieve some
compatibility between existing classes/metaclasses and their new ones.
But then we want to provide enough room for architecture specific optimizations.
Assuming that the function part of a method is funcallable outside of the context of
a generic function is a severe constraint. It limits seriously the amount of optimization
we can do (like distributing the overhead between the generic function and the method
function).
Furthermore, I don't think it is terribly useful for users to do this kind of thing.
If it is, one would think that the CLOS is not too powerful since people have or want
to bypass the method selection mechanism provided by the system (i.e generic function call).
From Gregor:
I think it is bad modularity to push whatever slot access optimization
implementations may want to do into the user's face, by tacking extra
arguments onto method functions where the user can see them.
Specifically, I think the way this is done in flavors (with
self-mapping-table as the first argument) is bad modularity, because the
user should be allowed to think that when they type:
(defmethod foo ((arg0 class) arg1 arg2)
(equal (si:all-args-to-this-function) (list arg0 arg1 arg2)))
foo will return t.
Of course this particular piece of code is not such a good example, and
any example will not be portable, by my point remains valid --
implementations should hide implementation details from the user.
Well, hiding implementation details from the user is the very reason why your
piece of code is not portable, Common Lisp never exposed the guts of a function.
There is a lot of implementation techniques out there for keyword arguments. For some
of them keyword arguments are not arguments but locals. So implementing actual function
with more or less "real" arguments is not something new.
My last point is: We will have some meta-object that the user can safely (portably)
mess around with (using generic functions defined in the metaclass protocol chapter of CLOS)
and some that the user will notice but will not be able to mess with in a portable way.
This is true of any open system. Lisp programmers are used to it.
Patrick.
∂08-Jan-87 2132 Bobrow.pa@Xerox.COM Re: What's left to do
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Jan 87 21:30:40 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 08 JAN 87 21:30:53 PST
Date: 8 Jan 87 21:30 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: What's left to do
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 08 Jan 87
17:14 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870108-213053-2356@Xerox>
1. Method combination. I am planning to answer Moon on this. We are
closer.
2,3. Change-class and Initialization protocol. Are their explicit
outstanding questions, or are Gregor's messages the current last word?
4. Class precedence list. I think your topological sort is a reasonable
specification. I would like to see my write-up in there as well. Try
putting both together. Mine describes a topological sort algorithm with
a preferred default order. And it describes the result of the usual
case simply.
danny
∂08-Jan-87 2321 Bobrow.pa@Xerox.COM Re: Method Combination Proposal
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Jan 87 23:20:57 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 08 JAN 87 23:20:01 PST
Date: 8 Jan 87 23:19 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Method Combination Proposal
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 6 Jan 87 21:57 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870108-232001-2402@Xerox>
I don't understand this reference to environment information.
I have never proposed any special programming environment
facilities here, other than the :description thing to control
printed representation. You're probably referring to my insistence
that macros that don't check their arguments, but just ignore
anything they don't recognize, are bad; I think this is a language
issue, not an environment issue.
Yes the :description is an environmental issue, and when error control
is done is environmental. I don't object to a macro checking its
arguments. It was the checking of methods that are not found that is at
issue (see next paragraph).
If I was going to do those programming environment facilities,
I would try to do them by calling the method-combination function
and seeing what happens, rather than by adding a new syntax to be
used in the define-method-combination specifically to convey that
information. This is similar to the suggestion that the best way
to find out what methods are actually called is to call the
method-combination function and analyze the Lisp form it returns,
rather than adding a new syntax for it to return a list of methods.
I don't understand how this helps in finding unacceptable methods (with
bad method qualifiers). There can be any number of reasons (e.g.
shadowing with no call-next-method) why the result of a method
combination does not include some applicable methods. So the result
cannot be what is checked. It must then be some use of the selection of
methods that is used. This is not specified (or only implicitly) by the
template language (and by FIND-METHODS).
Looking back over the old discussion, the motivation
for the find-methods scheme was stated to be simplicity...
Yes, and I haired it up (sorry). But, I think the language for
FIND-METHODS is an independent issue from whether FIND-METHODS should be
used for specifying subsets of methods or only the template language.
The real issue I believe is whether FIND-METHODS can only be used in a
define-method-combination body (in which case probably the template
language is as good as having the form) or whether there can be
sub-functions that use it; clearly they cannot have the template
language. I prefer having subfunctions have the same capabiities as
forms in the main body.
(define-method-combination mine ()
((methods (*)))
(grovel-my-method-combination #'make-method-call methods))
I found this very clever. However, I prefer to have the auxiliary
information in the metaobjects for the reasons you give.
With respect to the method-selection process, I was embarrased to hear
an argument I always use thrown back at me
"this would be done in Lisp instead of a special embedded language")
However, doesn't this put all the error checking in Lisp, even for the
simple cases. I was proposing a simple error checking template language
with :qualifier-set. Or, perhaps I just missed the dual purpose of the
method-group specifiers, to select AND error check the set of applicable
methods.
Are you saying that in place of the qualifier patterns one
could put the name of a predicate, in cases where the simple
pattern match language wasn't strong enough? That seems like a
good idea.
If we go with method-group specifiers, that is what I meant. The
predicate gets as an argument the list of all methods not yet selected
in the generic-function, and returns a subset.
If I had to rank my objections, my strongest one is
against the lambda list.
I'd like to understand why.
Four reasons:
1) It hairs up the syntax of both define-method-combination and
defgeneric-options
2) With no good simple example of its use, its utility is much in doubt
in my mind
3) In thinking about defining the arguments to the methods in the
meta-object protocol (e.g. compute-effective-method) I don't want to
have extra arguments sometimes.
4) Without this argument list, there is no need for a simple form of
DEFINE-METHOD-COMBINATION since the one form is simple enough. LEAN
proposal.
If the method combination arguments are constants for the generic
function, then a specialized generic function with such state is
sufficient. It does imply though that some mechanism must be found for
the user to get access to the generic-function in the body of
define-method-combination. You said you had one you liked in Flavors --
what is it.
Do we want to hair up defgeneric-options to allow extra state to be
specified? For example, one option of defgeneric-options could be
(:slots slot-name-1 slot-value1 ...)
I find this preferable since it extends a much more general facility to
the user.
In addition, I think the body of the method combination
should have access to the generic function in question. It
can't get it from the methods since methods can be on more than
one generic function.
I don't think that has been agreed to. It seems to be simpler
to allow sharing of method-functions, but not sharing of
method-objects.
After some more thought on this issue, I can't find a good case against
it. The form of argument against should be that one wants to change
some part of a method (say its function) and have this effect seen in
two generic functions. I cannot think of a plausible scenario.
Does this solve the access to the generic-function for
method-combination? Only if in the place where the generic function is
required there is a guarantee that a method is available. Is that
always possible?
PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT. I don't see that
this is an appropriate mechanism for dealing with this
optimization. It may just be the name which is upsetting me, I
am not sure yet.
The other way to deal with this is to make it a keyword
argument to make-method-call, which defaults to (eq operator
'progn). I would be happy with that; in fact I think it's what I
proposed originally, but when we discussed this in Menlo Park, the
change to PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT was made (I forget
who proposed it and what the arguments were). Note that the simple
form of DEFINE-METHOD-COMBINATION would need this keyword argument
too.
The objections to the keyword were
1) it was an extra keyword
2) this information was something that was useful in more than this
context. Other method-combination types and other program constructing
programs can use the same information. Can we push this problem into the
COMPILER group for CommonLisp, and assume that they will propose
something like this? It seems inappropriate for the object standard.
To my way of thinking, the syntax of DEFINE-METHOD-COMBINATION
is similar to the syntax of DEFMACRO and DEFSETF. By the way,
Flavors' DEFINE-METHOD-COMBINATION doesn't allow doc-strings.
Should we leave this out and allow this to be something beat back in by
the committee if necessary (Gives them a chance to piss on something).
danny
∂08-Jan-87 2341 Bobrow.pa@Xerox.COM Re: Class Precedence List
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Jan 87 23:41:27 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 08 JAN 87 23:41:15 PST
Date: 8 Jan 87 23:41 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Class Precedence List
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 08 Jan 87
20:01 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870108-234115-2419@Xerox>
[Danny's] algorithm gives primacy to the preorder treewalk, and
there is a question about whether the algorithm terminates - though
it's actually easy to prove if the algorithm is stated clearly -
and about how the error condition is computed.
This primacy is good I claim, because in the simple (and usual) case it
describes the result of the sort. It is primary in how people will try
to simulate the algorithm. There is no question about whether the
algorithm terminates, or the error condition (though perhaps it would be
more clearly stated in terms of the partial order). How does the
topological sort algorithm state the error condition about loops?
EXAMPLE 2(not repeated here)
admits a single possibility by his rules, which is
(pie apple fruit cinnamon spice food)
Not by my interpretation of his rules (not including the Flavors extra
rule about superclasses). Why determines the order of fruit and spice?
What determines the order in your algorithm except the preorder.
I also propose that implementations be encouraged to offer a
means of warning or signalling an error every time that appeal is
made to the preorder.
Again this is the usual case where one has independent mixins with
superclasses. So no warning please.
By the way, this DAG is not a lattice in that there is no "meaningful"
lower bound for any two classes. But I believe we have agreed on a top
of T in any event.
So my conclusion is that your description is a good mathematical one,
and should be included. Mine is a good operational one, and should be
included. And both agree with Moon's algorithm with the other Flavors
rule, so we are all right.
danny
∂08-Jan-87 2342 Bobrow.pa@Xerox.COM Re: Lexical environment of slot default initial value forms
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Jan 87 23:42:25 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 08 JAN 87 23:42:43 PST
Date: 8 Jan 87 23:42 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Lexical environment of slot default initial value forms
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 8 Jan 87 19:59 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870108-234243-2424@Xerox>
We discussed this and concluded that the lexical environment
should be the lexical environment where the form originally
appeared, i.e. the lexical environment in which defclass was
evaluated, and the dynamic environment should be the one in effect
at the time the form is evaluated.
Sounds right.
danny
∂08-Jan-87 2349 Bobrow.pa@Xerox.COM Re: Issues for the CLOS committee to start focussing on
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Jan 87 23:49:08 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 08 JAN 87 23:48:51 PST
Date: 8 Jan 87 23:48 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Issues for the CLOS committee to start focussing on
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 8 Jan 87 23:25 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870108-234851-2441@Xerox>
We need to define quite explicitly the inheritance behavior of
class options and slot options. There should be a table listing
each option and showing how it inherits.
I made a set of suggestions for this. If one of the writers could turn
that into English and find where the holes are, I would be glad to
follow up (I don't have time for extensive writing at the moment).
Class variables.
(Discussion is ongoing, probably almost finished)
What is your belief about the state of this. I made a detailed
suggestion last.
Some of the functions in the Functions chapter don't make sense
without the rest of meta-objects. Perhaps it should be reorganized
into two chapters.
I will be trying with Gregor to add as much more of the meta-object
protocol as possible after he gets back at the end of next week. I
would suggest sending it out even if we don't agree on all of it, but
this can wait, pending seeing it.
danny
∂09-Jan-87 0612 skeene@STONY-BROOK.SCRC.Symbolics.COM Re: Issues for the CLOS committee to start focussing on
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jan 87 06:12:37 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 39604; Fri 9-Jan-87 09:12:09 EST
Date: Fri, 9 Jan 87 09:10 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Issues for the CLOS committee to start focussing on
To: Bobrow.pa@Xerox.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM,
Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870108-234851-2441@Xerox>
Message-ID: <870109091029.3.SKEENE@JUNCO.SCRC.Symbolics.COM>
Line-fold: No
Date: 8 Jan 87 23:48 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
We need to define quite explicitly the inheritance behavior of
class options and slot options. There should be a table listing
each option and showing how it inherits.
I made a set of suggestions for this. If one of the writers could turn
that into English and find where the holes are, I would be glad to
follow up (I don't have time for extensive writing at the moment).
I'll get to work on this.
danny
∂09-Jan-87 1154 RPG Class Precedence List: Rebuttal to Danny
To: common-lisp-object-system@SAIL.STANFORD.EDU
Danny writes:
``This primacy [of the preorder] is good I claim, because in the simple
(and usual) case it describes the result of the sort.''
I guess Danny means that he expects most people will build a tree, except
for the lattice requirement of the class named T being at the top; in this
case he's right. But, if you have almost any nontrivial structure to the
upper part of the lattice, it is a big mistake for users to adopt this
mental model.
Here is a possibly too large and too ugly example:
(defclass c1 () ())
(defclass c2 () ())
(defclass c3 () ())
(defclass e1 (c1) ())
(defclass e2 (c2) ())
(defclass e3 (c3) ())
(defclass e4 (e3 e2 e1) ())
(defclass e5 (c1 c2) ())
(defclass e6 (c2 c3) ())
(defclass e7 (e5 e6 e4) ())
If a user does a preorder treewalk to guess how the total order will
look, he will get the following.
1. If he eliminates duplicates from the front of the list:
(E7 E5 E6 E4 E3 C3 E2 C2 E1 C1)
2. If he eliminates duplicates from the rear of the list:
(E7 E5 C1 C2 E6 C3 E4 E3 E2 E1)
Meanwhile, the total order looks like:
(E7 E5 E6 E4 E3 E2 E1 C1 C2 C3)
Well, option 1 is correct to the halfway point, so I suppose half right is
better than nothing. On the other hand, option 2 gets the critical
and curious relatives order of (E3,E2,E1) and (C1,C2,C3) right. Hard to
know which a user would be better off with.
I should mention, as a curiosity, that my algorithm makes no appeal to the
preorder when computing the class precedence list for E7: The user would
be, therefore, encouraged to use the very thing that is irrelevant to the
total order to intuit that total order.
Danny writes:
``It is primary in how people will try to simulate the algorithm.''
I think we should discourage users from using preorder to simulate the
algorithm. They will lose unless the lattice is mostly like a tree. I
think users knowing that the local precedence orders are very important
and providing tools to look at the total orders at classes is the only
good option.
Danny writes:
``There is no question about whether the algorithm terminates....''
I agreed it is clear to me that the algorithm terminates. I stated that
a reader might be puzzled by this question.
Danny asks:
``How does the topological sort algorithm state the error condition about
loops?''
The sort terminates when it can not find a class that is preceeded by
no others. If, when the sort terminates, there are classes left to be
sorted, then there is a loop in the relations.
Danny writes:
`` EXAMPLE 2 (not repeated here)
admits a single possibility by his rules, which is
(pie apple fruit cinnamon spice food)
Not by my interpretation of his rules....''
This is the example Moon uses in the document ``Common Lisp Classes:
A Draft Object-oriented Standard'' on page 30 under the heading ``Example
of a Tree Walk.'' I claim it admits a single possibility by Moon's
interpretation of Moon's rules.
Danny asks:
``What determines the order of fruit and spice [in Moon's algorithm]?
What determines the order in your algorithm except the preorder?''
In Moon's algorithm the preorder determines it along with the fact that
the local precedence orders never veto the preorder constraint.
In my algorithm the preorder arbitrates.
Danny writes:
`` [quote: rpg]
I also propose that implementations be encouraged to offer a
means of warning or signalling an error every time that appeal is
made to the preorder.
[unquote: rpg]
Again this is the usual case where one has independent mixins with
superclasses. So no warning please.''
I suppose I should be more precise with my language.
I propose that implementations be encouraged to provide a special variable
called *warn-on-nondeterminism-in-topological-sort*, for example, whose
default value is NIL and such that when its value is non-null the
algorithm that computes the class precedence list warns the user (or
signals an error) when it encounters a situation in which the topological
sort cannot uniquely determine a total order from the partial orders.
The point of this variable is that the explicit constraints that the user
writes - the subclass-superclass relations and the local precedence orders
- ought to uniquely determine the total order, because these are the only
things that he directly manipulates. When the class precedence list
computation relies on the preorder, it is looking at some more global structure
of the lattice when the direct constraints underconstrain the total order.
``So no warning please'' translates into (setq *warn...* nil).
Well, I won't press on this issue too much. I think, however, that without
tools to display the class precedence list programmers will be stumped
a lot of the time.
Danny writes:
``By the way, this DAG is not a lattice in that there is no "meaningful"
lower bound for any two classes. But I believe we have agreed on a top of
T in any event.''
I think the document requires a ``"meaningless"'' bottom element, which is
the class named NIL. If we decide we don't like that, then we can describe
it as a set of lattices rooted at the class named T, or as a directed
acyclic graph with a distinguished element that is the class named T. I
think it's nicer to say we have a lattice than a set of lattices or a
directed acyclic graph, but this, I believe, is a matter of taste. Except
for being able to state that one aspect of the partial order on the
structure is the lattce order, there is no reason for it - we can always
explain that when you compute the class precedence list for a class, you
have a lattice with top the class named T and bottom that given class.
The meaningless bottom element can have a local precedence order that reflects
the order in which the classes directly above it were created.
Danny concludes:
``So my conclusion is that your description is a good mathematical one,
and should be included. Mine is a good operational one, and should be
included. And both agree with Moon's algorithm with the other Flavors
rule, so we are all right.''
I've already explained why I think your algorithm results in potential
confusion in readers of a description of it. Of course, your algorithm
has been, up to now, subjected to no very strenuous writing onslaught.
-rpg-
∂09-Jan-87 1349 Moon@RIVERSIDE.SCRC.Symbolics.COM Re: What's left to do
Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jan 87 13:49:04 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 91932; Fri 9-Jan-87 16:50:07 EST
Date: Fri, 9 Jan 87 16:47 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: What's left to do
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870108-213053-2356@Xerox>
Message-ID: <870109164709.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 8 Jan 87 21:30 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
2,3. Change-class and Initialization protocol. Are their explicit
outstanding questions, or are Gregor's messages the current last word?
You've probably seen my message on this by now, but just in case: I
haven't started on these yet, since I wanted to concentrate on finishing
method-combination first. I expect that there are a lot of outstanding
questions, in spite of the quietness of the mail. I plan to work on
both of these (initialization first) next week. I anticipate a lot of
interruptions and other demands on my time next week, but I hope to get
through these issues in spite of that.
∂09-Jan-87 1359 skeene@RIVERSIDE.SCRC.Symbolics.COM new version of concepts chapter
Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jan 87 13:59:06 PST
Received: from JUNCO.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 91936; Fri 9-Jan-87 16:59:49 EST
Date: Fri, 9 Jan 87 16:56 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: new version of concepts chapter
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870109165636.4.SKEENE@JUNCO.SCRC.Symbolics.COM>
I wrote a new version of concepts.tex (and copied it to concepts.7).
The changes were mainly editorial. I still want a "hold" on the file,
because I need to make more changes on Monday.
∂09-Jan-87 1744 Bobrow.pa@Xerox.COM Re: Class Precedence List: Rebuttal to Danny
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jan 87 17:44:10 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 09 JAN 87 16:59:38 PST
Date: 9 Jan 87 16:59 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Class Precedence List: Rebuttal to Danny
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 09 Jan 87
11:54 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870109-165938-3473@Xerox>
Danny writes:
``This primacy [of the preorder] is good I claim, because in
the simple (and usual) case it describes the result of the sort.''
I guess Danny means that he expects most people will build a
tree, except for the lattice requirement of the class named T being
at the top; in this case he's right. But, if you have almost any
nontrivial structure to the upper part of the lattice, it is a big
mistake for users to adopt this mental model.
There is a simple rule. If any mixin appears more than once, and not in
last position in the local supers, then the user must apply the movement
rules. I claim this is relatively rare, although it is easy to
construct examples. (Dave do you have data on this? How many flavors
have components that share mixins where the mixins are not last in the
chain?)
Thus it is both easy to construct the usual list, and easy to know when
the movement rules are to apply.
The example you give is clearly has the property I gave, and the
movement rule is easy for this case.
(defclass c1 () ())
(defclass c2 () ())
(defclass c3 () ())
(defclass e1 (c1) ())
(defclass e2 (c2) ())
(defclass e3 (c3) ())
(defclass e4 (e3 e2 e1) ())
(defclass e5 (c1 c2) ())
(defclass e6 (c2 c3) ())
(defclass e7 (e5 e6 e4) ())
He eliminates duplicates from the front of the list:
(E7 E5 E6 E4 E3 C3 E2 C2 E1 C1)
Now going from the left, C3 depends directly on C2, so move it past all
of it dependendents (this means C1). Then coming to C2, move it past
its dependents getting
(E7 E5 E6 E4 E3 E2 E1 C1 C2 C3)
Danny writes:
``It is primary in how people will try to simulate the
algorithm.''
I think we should discourage users from using preorder to
simulate the algorithm. They will lose unless the lattice is mostly
like a tree. I think users knowing that the local precedence
orders are very important and providing tools to look at the total
orders at classes is the only good option.
I think it is foolhardy to try to discourage programmers from thinking
about algorithms. They are not mathematicians. Who could argue that it
is bad to provide tools to look at the total orders at classes, but for
understnadability off line, they should have an easy way to think about
construction of the list.
Danny asks:
``How does the topological sort algorithm state the error
condition about loops?''
The sort terminates when it can not find a class that is
preceeded by no others. If, when the sort terminates, there are
classes left to be sorted, then there is a loop in the relations.
I don't understand. If e3 in the above example had (c3 c2) as supers,
where would it fail?
Danny asks:
``What determines the order of fruit and spice [in Moon's
algorithm]? What determines the order in your algorithm except the
preorder?''
In Moon's algorithm the preorder determines it along with the
fact that the local precedence orders never veto the preorder
constraint.
In my algorithm the preorder arbitrates.
Sounds like the preorder determines it. Moons constraints don't
determine it though -- only the algorithm (except for the "hidden"
flavor rule he told us about.)
The point of this variable is that the explicit constraints
that the user writes - the subclass-superclass relations and the
local precedence orders - ought to uniquely determine the total
order, because these are the only things that he directly
manipulates. When the class precedence list computation relies on
the preorder, it is looking at some more global structure of the
lattice when the direct constraints underconstrain the total order.
But you ignore the fact the the user does not want to directly constrain
the total order. If two mixins C1 and D1 live in a hierarchy, and C1
inherits from C2 inherits from C3, and D1 from D2 and D2 from D3, then
anything that contains C and D will have many possible total orders.
Did I care? Didn't I want a fixed one obeying Moon's hidden rule, so
that splitting a class doesn't change behavior. So no variable either.
I think the document requires a ``"meaningless"'' bottom
element, which is the class named NIL.
We could merely apologize for the slight misuse of the term "lattice"
and call it one from then on. Possbily alluding to the fact that the
user has been allowed to not be burdened with the NIL class.
I've already explained why I think your algorithm results in
potential confusion in readers of a description of it. Of course,
your algorithm has been, up to now, subjected to no very strenuous
writing onslaught.
I think I have answered you, and good writing is indeed called for.
danny
∂10-Jan-87 2101 RPG For the Record
To: common-lisp-object-system@SAIL.STANFORD.EDU
1. I like Moon's expanded pattern language proposal: It's
the one where the third subform of define-method-combination
becomes
({ (variable {qualifier-pattern}+ {keyword argument}*)
| (variable predicate-symbol {keyword argument}*) }*)
2. I basically don't like pattern languages, but in this case
I believe the alternatives are worse. Many pattern languages I
know of use the character ``*'' to mean ``match 0 or more items.''
This minor objection can be ignored.
3. I believe Moon's analysis of make-method-combination and why
it makes sense to not explicitly pass the so-called ``id'' information.
Was I mistaken in believing that Moon's counter to Gregor's code should
have been:
(define-method-combination mine ()
((methods (*)))
(grovel-my-method-combination #'make-method-call methods))
(defun grovel-my-method-combination (make-method-call methods)
..
(funcall make-method-call methods :operator 'foo)
..)
4. Some potential users have asked me to bring up the subject of
CALL-NEXT-METHOD passing altered arguments to the next method.
This has been disallowed because the next method might get arguments
that don't conform to its parameter qualifiers. Is there further
discussion?
-rpg-
∂11-Jan-87 1207 RPG Issues for the CLOS committee to start focussing on
To: common-lisp-object-system@SAIL.STANFORD.EDU
Here is a reproduction of part of Moon's message with some statements
about how things are going on the issues [enclosed in square brackets].
Consistent terminology
- names for relationships among classes
[In the concepts file I have made the following definitions and
terminology conventions:
``direct superclass'' means immediate parent.
``direct subclass'' means immediate daughter.
``superclass'' means direct superclass or direct superclass of a direct
superclass or etc.
``subclass'' is similar.
I've defined the phrase ``classes at or above a given class'' to mean
what ``component'' means in New Flavors documentation. It means the set
of superclasses of a class along with the class itself. Mathematics provides
no help except that we could chose to define a class to be a superclass of
itself.]
- names for predefined classes & other interesting entities
[I did nothing here.]
- describing the terminology at the front of the document
[The concepts file, being the front of the document, defines these
terms as it goes.]
- making sure the document adheres everywhere to the chosen terminology
(this may have been resolved already, but we were still discussing
it quite recently)
[The concepts file adheres everywhere. If people agree to the way it reads,
I'll extend it to the functions file.]
Method-combination.
[This has two aspects: the general theory of how generic functions cause
method combination to happen and the syntax of defining new method combination
types. I took Sonya's text for the first aspect and tried to make it more
understandable - I think it's a little better now. I think the hard part was
explaining why it works like macro expansion instead of simply doing it.]
The class precedence rules, description, and algorithm. To a certain
extent these are three separate issues.
(Dick has been working on this, but I don't think it's resolved yet)
[I added a test description of the rules based on the topological sort
approach in concepts. My description still recommends optionally
signalling errors in cases where multiple orders are possible but preorder
has disambiguated. I think there is a consensus to remove this, and I will
as soon as Sonya is finished with the file. I think it reads pretty well.
It might be a good idea to include, as an implementation note, a
description of Moon's rules and algorithm as an example of an equivalent
implementation, or of Danny's, but I don't plan to do it.
My description requires that we make the class DAG a lattice, which means
a bottom as well as a top element. We haven't decided this, but I don't
think it's a big deal to do it. If we don't do it and go with alternatives
like calling it a lattice though it isn't, I think we risk ridicule.
The one reasonable alternative is to define it to be a DAG with a distiniguished
element, and when we compute the CPL, we get a local lattice.]
-rpg-
∂11-Jan-87 1208 RPG Environment for initial value form
To: common-lisp-object-system@SAIL.STANFORD.EDU
The lexical environmemt in which the defclass happens is right.
-rpg-
∂11-Jan-87 2230 Bobrow.pa@Xerox.COM Re: Issues for the CLOS committee to start focussing on
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Jan 87 22:30:14 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 11 JAN 87 22:22:59 PST
Date: 11 Jan 87 22:22 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Issues for the CLOS committee to start focussing on
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 11 Jan 87
12:07 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870111-222259-4265@Xerox>
Terminology
Is the following used consistently?
"An instance q is of type X if (CLASS q) is X or a subclass of X; that
is X is at or above the (CLASS q)" Is "type" the right word here?
Seems right to me, given the joining of the type and class spaces.
The name for standard method combination in the concepts document, and
elsewhere whould be "standard" not daemon.
My description requires that we make the class DAG a lattice,
which means a bottom as well as a top element. We haven't decided
this, but I don't think it's a big deal to do it.
The only issue here is making it clear and getting the right name for
the bottom. From the point of view of agreeing with the type system,
NIL is the right name for the bottom, since NIL is a defined Common Lisp
type. But what happens when people evaluate (CLASS-NAMED NIL). Do they
get a real class? Or should (CLASS-NAMED NIL) signal an error?
If we have unnamed classes, then
(NEQ (CLASS-NAMED (CLASS-NAME <unnamed-class>)) <unnamed-class>)
which is OK with me.
danny
∂11-Jan-87 2240 Bobrow.pa@Xerox.COM Re: For the Record
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Jan 87 22:40:03 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 11 JAN 87 22:31:28 PST
Date: 11 Jan 87 22:31 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: For the Record
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 10 Jan 87
21:01 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870111-223128-4273@Xerox>
4. Some potential users have asked me to bring up the subject
of CALL-NEXT-METHOD passing altered arguments to the next method.
This has been disallowed because the next method might get
arguments that don't conform to its parameter qualifiers. Is there
further discussion?
I don't think this should be disallowed. I think argument checking
should be done, and an error signalled if types of discriminated
arguments have changed. In most simple cases, I would think this check
can be compiled away (no rebinding or setting of the incoming arguments,
and the name used in the call). An (ugly) alternative is to provide
keyword syntax of some sort for changing just those arguments desired
(call-next-method x new-value-of-x).
1. I like Moon's expanded pattern language proposal: It's
the one where the third subform of define-method-combination
becomes ({ (variable {qualifier-pattern}+ {keyword argument}*)
| (variable predicate-symbol {keyword argument}*) }*)
In case I wasn't clear, I like this extension too. The only question
was whether we should have a patter language, and always use Lisp in a
subfunction.
danny
∂11-Jan-87 2323 RPG CPL Algorithm
To: bobrow.pa@XEROX.COM, "#CLOOPS.MSG[COM,LSP]"@SAIL.STANFORD.EDU
Suppose we want to compute the CPL for X.
Let CL be the classes at or above X; let R be the explicit relations
that reflect the lattice order and local precedence orders.
Here's an example:
(defclass pie (apple cinnamon) ())
(defclass apple (fruit) ())
(defclass cinnamon (spice) ())
(defclass fruit (food) ())
(defclass spice (food) ())
(defclass food () ())
CL = {pie,apple,cinnamon,fruit,spice,food}
R = {pie<apple
pie<cinnamon
apple<cinnamon
apple<fruit
cinnamon<spice
fruit<food
spice<food}
Now we topologically sort the elements of CL. This is done as follows.
Select a class C that is not preceded by any other. Put it first in the
order. If there are several such classes, select the one that comes first
in preorder. Remove C from CL and remove all relations that mention it.
This new CL is again partially ordered by the new pairs. Continue until
CL is empty.
PIE is preceded by nothing, so it goes first. Remove PIE from CL and
the first two relations from R.
Order = {PIE}
CL = {apple,cinnamon,fruit,spice,food}
R = {apple<cinnamon
apple<fruit
cinnamon<spice
fruit<food
spice<food}
APPLE is next.
Order = {PIE,APPLE}
CL = {cinnamon,fruit,spice,food}
R = {cinnamon<spice
fruit<food
spice<food}
CINNAMON or FRUIT could come next. The preorder treewalk visits classes
in this order: PIE, APPLE, FRUIT, FOOD, CINNAMON, SPICE.
FRUIT is, therefore, next.
Order = {PIE,APPLE,FRUIT}
CL = {cinnamon,spice,food}
R = {cinnamon<spice
spice<food}
CINNAMON is next.
Order = {PIE,APPLE,FRUIT,CINNAMON}
CL = {spice,food}
R = {spice<food}
SPICE is next.
Order = {PIE,APPLE,FRUIT,CINNAMON,SPICE}
CL = {food}
R = {}
FOOD comes last:
Order = {PIE,APPLE,FRUIT,CINNAMON,SPICE,FOOD}
CL = {}
R = {}
-rpg-
∂12-Jan-87 0028 Bobrow.pa@Xerox.COM Re: CPL Algorithm
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 12 Jan 87 00:28:17 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 12 JAN 87 00:15:06 PST
Date: 12 Jan 87 00:14 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: CPL Algorithm
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 11 Jan 87
23:23 PST
To: RPG@SAIL.STANFORD.EDU
cc: bobrow.pa@Xerox.COM, "#CLOOPS.MSG[COM,LSP]"@SAIL.STANFORD.EDU
Message-ID: <870112-001506-4303@Xerox>
Well now I understand it. But I hate simulating it in my head. In the
write-up, it at least ought to say that for most simple cases it follows
the rule "left-to-right depth first up to joins". Only if that violates
a constraint ... Pleazse give the naive user a simple rule, or
describe a number of simple examples for simple cases, even if you don't
include my algorithm or Moon's.
danny
∂12-Jan-87 1531 Moon@RIVERSIDE.SCRC.Symbolics.COM Documents updated for method combination
Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 12 Jan 87 15:30:11 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 92382; Mon 12-Jan-87 18:31:20 EST
Date: Mon, 12 Jan 87 18:28 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Documents updated for method combination
To: Common-Lisp-Object-System@SU-AI.ARPA
Message-ID: <870112182842.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
I have updated CONCEP.TEX[CLS,LSP] for method combination, and copied
it to CONCEP.8. The file DMC.FUN[CLS,LSP] contains sections to be
inserted into the functions document when that document unfreezes,
however these sections haven't been fully converted to TEX yet.
This is the updating I promised to do last Friday (it took longer than
expected).
I believe this reflects the result of the discussions we've had over
the mail, but if I have slighted anyone's point of view I apologize,
and I encourage you to write up a dissenting proposal and add it to
the file. I plan to turn my own attention to some of the other
outstanding issues, in an effort to get to a reasonable (but not
unchangeably final by any means) document by the next X3J13 meeting,
so I won't be doing anything more on method combination this month
if I can help it.
∂12-Jan-87 1547 Moon@RIVERSIDE.SCRC.Symbolics.COM Re: Method Combination Proposal
Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 12 Jan 87 15:46:47 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 92390; Mon 12-Jan-87 18:47:52 EST
Date: Mon, 12 Jan 87 18:45 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Method Combination Proposal
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870108-232001-2402@Xerox>
Message-ID: <870112184516.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Here are answers reflecting what I put into the document.
Date: 8 Jan 87 23:19 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
If I was going to do those programming environment facilities,
I would try to do them by calling the method-combination function
and seeing what happens, rather than by adding a new syntax to be
used in the define-method-combination specifically to convey that
information. This is similar to the suggestion that the best way
to find out what methods are actually called is to call the
method-combination function and analyze the Lisp form it returns,
rather than adding a new syntax for it to return a list of methods.
I don't understand how this helps in finding unacceptable methods (with
bad method qualifiers). There can be any number of reasons (e.g.
shadowing with no call-next-method) why the result of a method
combination does not include some applicable methods. So the result
cannot be what is checked. It must then be some use of the selection of
methods that is used. This is not specified (or only implicitly) by the
template language (and by FIND-METHODS).
I straightened this out, I think (as much as I could without depending on
the condition system that has been proposed but not yet adopted). There
is a function, INVALID-METHOD-ERROR, which is called with the offending
method object as an argument, along with a string error message. The
programming environment can make this function do what it needs.
Looking back over the old discussion, the motivation
for the find-methods scheme was stated to be simplicity...
Yes, and I haired it up (sorry). But, I think the language for
FIND-METHODS is an independent issue from whether FIND-METHODS should be
used for specifying subsets of methods or only the template language.
The real issue I believe is whether FIND-METHODS can only be used in a
define-method-combination body (in which case probably the template
language is as good as having the form) or whether there can be
sub-functions that use it; clearly they cannot have the template
language. I prefer having subfunctions have the same capabiities as
forms in the main body.
I agree with the last sentence and I tried to make that the case as much
as possible in the latest version. It's not quite perfect but I think
it's adequate.
(define-method-combination mine ()
((methods (*)))
(grovel-my-method-combination #'make-method-call methods))
I found this very clever. However, I prefer to have the auxiliary
information in the metaobjects for the reasons you give.
This was so clever that I flushed it. Consulting notes and the rationale
section, we had already decided that we shouldn't do it this way and that
the extra information should be passed as special variables, not lexically.
So I changed it to work that way.
With respect to the method-selection process, I was embarrased to hear
an argument I always use thrown back at me
"this would be done in Lisp instead of a special embedded language")
However, doesn't this put all the error checking in Lisp, even for the
simple cases. I was proposing a simple error checking template language
with :qualifier-set. Or, perhaps I just missed the dual purpose of the
method-group specifiers, to select AND error check the set of applicable
methods.
The explanation and motivation should be much better and clearer now.
Are you saying that in place of the qualifier patterns one
could put the name of a predicate, in cases where the simple
pattern match language wasn't strong enough? That seems like a
good idea.
If we go with method-group specifiers, that is what I meant. The
predicate gets as an argument the list of all methods not yet selected
in the generic-function, and returns a subset.
I put this in, except I made the predicate get applied separately to each
method (actually to the qualifier list of the method), since I thought that
would be easier for the user and it's no less general. Also it shouldn't
be called a predicate if the value isn't true/false.
If I had to rank my objections, my strongest one is
against the lambda list.
I'd like to understand why.
Four reasons:
1) It hairs up the syntax of both define-method-combination and
defgeneric-options
This is weak. I don't see any significant complexity increase.
2) With no good simple example of its use, its utility is much in doubt
in my mind
This is strong.
3) In thinking about defining the arguments to the methods in the
meta-object protocol (e.g. compute-effective-method) I don't want to
have extra arguments sometimes.
It's just a list, not a variable number of arguments. (We're using the
word "arguments" to mean two different things. One is the arguments
given to the compute-effective-method generic function; the other is the
syntax of the :method-combination option to defgeneric-options, which
includes a "name" possibly followed by "arguments."). I think I wrote
this more clearly in the latest document; let me know how you like it.
4) Without this argument list, there is no need for a simple form of
DEFINE-METHOD-COMBINATION since the one form is simple enough. LEAN
proposal.
This is not true; I hope I've made things clear enough in the latest version
of the document that it's now obvious why it's not true.
In spite of #2, I left the lambda-list in, because of the need to pass
in the generic-function. We can discuss that more if it's a problem.
If the method combination arguments are constants for the generic
function, then a specialized generic function with such state is
sufficient.
I don't think a special magic way to put information into slots of the
generic-function and another special magic way to get it out again can
be considered less hairy syntax than a lambda-list. Programmers are
already familiar with lambda-lists.
It does imply though that some mechanism must be found for
the user to get access to the generic-function in the body of
define-method-combination. You said you had one you liked in Flavors --
what is it.
I didn't say that. We have one I -dislike-, which is that a variable with
a magic name in a magic package is bound to the generic-function.
Do we want to hair up defgeneric-options to allow extra state to be
specified? For example, one option of defgeneric-options could be
(:slots slot-name-1 slot-value1 ...)
I find this preferable since it extends a much more general facility to
the user.
I find this definitely excessive. It's using an H-bomb to kill a fly, and
also is syntactically poor because not all of the :method-combination
information would be in one place in the defgeneric-options.
In addition, I think the body of the method combination
should have access to the generic function in question. It
can't get it from the methods since methods can be on more than
one generic function.
I don't think that has been agreed to. It seems to be simpler
to allow sharing of method-functions, but not sharing of
method-objects.
After some more thought on this issue, I can't find a good case against
it. The form of argument against should be that one wants to change
some part of a method (say its function) and have this effect seen in
two generic functions. I cannot think of a plausible scenario.
I agree with you here, but...
Does this solve the access to the generic-function for
method-combination? Only if in the place where the generic function is
required there is a guarantee that a method is available. Is that
always possible?
...I wasn't so sure that getting the generic-function from the methods
was a good idea after all, because I can see cases where a method isn't
easily available, and because we might change our mind for some reason
about the data structure having a reference from a method to its
generic-function, so it didn't seem wise to depend on it. Instead I
just made the generic-function be passed as an argument, which seems
simplest all around except that you have to put in a declare ignore if
you don't use it, to be strict Common Lisp.
PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT. I don't see that
this is an appropriate mechanism for dealing with this
optimization. It may just be the name which is upsetting me, I
am not sure yet.
The other way to deal with this is to make it a keyword
argument to make-method-call, which defaults to (eq operator
'progn). I would be happy with that; in fact I think it's what I
proposed originally, but when we discussed this in Menlo Park, the
change to PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT was made (I forget
who proposed it and what the arguments were). Note that the simple
form of DEFINE-METHOD-COMBINATION would need this keyword argument
too.
The objections to the keyword were
1) it was an extra keyword
Better an extra keyword than an extra function, surely.
2) this information was something that was useful in more than this
context. Other method-combination types and other program constructing
programs can use the same information. Can we push this problem into the
COMPILER group for CommonLisp, and assume that they will propose
something like this? It seems inappropriate for the object standard.
I decided that it was a mistake to associate this with the compiler, and
that this was really highly specific to method-combination, so I took
out the extra function and put the extra keyword back in. I am now
completely convinced that it's wrong to do this with a function. If
people want to argue that it shouldn't be done at all, we can talk about
that. I put some motivational explanation into the document.
To my way of thinking, the syntax of DEFINE-METHOD-COMBINATION
is similar to the syntax of DEFMACRO and DEFSETF. By the way,
Flavors' DEFINE-METHOD-COMBINATION doesn't allow doc-strings.
Should we leave this out and allow this to be something beat back in by
the committee if necessary (Gives them a chance to piss on something).
I think it's better to be consistent. There are more useful places for
them to piss.
∂12-Jan-87 1828 Moon@STONY-BROOK.SCRC.Symbolics.COM For the Record
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 12 Jan 87 18:28:30 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 41998; Mon 12-Jan-87 21:27:55 EST
Date: Mon, 12 Jan 87 21:26 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: For the Record
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 11 Jan 87 00:01 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870112212650.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 10 Jan 87 2101 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
4. Some potential users have asked me to bring up the subject of
CALL-NEXT-METHOD passing altered arguments to the next method.
This has been disallowed because the next method might get arguments
that don't conform to its parameter qualifiers. Is there further
discussion?
I think there should be. I've added this to the list of issues on my
whiteboard, whence it will likely migrate to more permanent storage.
However, we may not get to this before the Feb 4 deadline, since there
are more critical things to do first.
Note that the issue of CALL-NEXT-METHOD passing altered arguments to the
next method is very closely connected with the issue of MAKE-METHOD-CALL
passing altered arguments.
∂12-Jan-87 1836 Moon@STONY-BROOK.SCRC.Symbolics.COM Environment for initial value form
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 12 Jan 87 18:36:05 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 42006; Mon 12-Jan-87 21:35:10 EST
Date: Mon, 12 Jan 87 21:34 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Environment for initial value form
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 11 Jan 87 15:08 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870112213405.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 11 Jan 87 1208 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
The lexical environmemt in which the defclass happens is right.
Everyone who spoke up agrees with this, but the document doesn't say it yet.
Let's not drop this one through the cracks.
∂12-Jan-87 1945 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Issues for the CLOS committee to start focussing on
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 12 Jan 87 19:45:22 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 42048; Mon 12-Jan-87 22:44:29 EST
Date: Mon, 12 Jan 87 22:43 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Issues for the CLOS committee to start focussing on
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870108-234851-2441@Xerox>
Message-ID: <870112224325.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 8 Jan 87 23:48 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Class variables.
(Discussion is ongoing, probably almost finished)
What is your belief about the state of this. I made a detailed
suggestion last.
Danny, I assume you're asking me, since I was the TO: recipient.
My belief is that it hasn't converged yet, but is close. I don't think
I've read your detailed suggestion carefully yet. This issue isn't
one of the next three on my priority list; if you'd rather I thought
about this first, though, let me know and I will.
∂12-Jan-87 1950 Moon@STONY-BROOK.SCRC.Symbolics.COM For the Record
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 12 Jan 87 19:49:50 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 42053; Mon 12-Jan-87 22:49:11 EST
Date: Mon, 12 Jan 87 22:48 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: For the Record
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 11 Jan 87 00:01 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870112224807.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 10 Jan 87 2101 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Was I mistaken in believing that Moon's counter to Gregor's code should
have been:
(define-method-combination mine ()
((methods (*)))
(grovel-my-method-combination #'make-method-call methods))
(defun grovel-my-method-combination (make-method-call methods)
..
(funcall make-method-call methods :operator 'foo)
..)
Right. What an embarrassing and understandability-destroying typo!
(I had (funcall #'make-method-call methods :operator 'foo) !)
∂13-Jan-87 1045 Bobrow.pa@Xerox.COM Re: Issues for the CLOS committee to start focussing on
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 13 Jan 87 10:42:50 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 13 JAN 87 10:38:35 PST
Date: 13 Jan 87 10:38 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Issues for the CLOS committee to start focussing on
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 12 Jan 87 22:43 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870113-103835-6035@Xerox>
Date: 8 Jan 87 23:48 PST From: Danny Bobrow
<Bobrow.pa@Xerox.COM>
Class variables. (Discussion is ongoing, probably almost
finished)
What is your belief about the state of this. I made a
detailed suggestion last.
Danny, I assume you're asking me, since I was the TO:
recipient. My belief is that it hasn't converged yet, but is close.
I don't think I've read your detailed suggestion carefully yet.
This issue isn't one of the next three on my priority list; if
you'd rather I thought about this first, though, let me know and I
will.
Sonya said she would write up what I had suggested in English, and we
can go from there. (Right Sonya?)
danny
∂13-Jan-87 2046 skeene@RIVERSIDE.SCRC.Symbolics.COM Re: Issues for the CLOS committee to start focussing on
Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 13 Jan 87 14:44:57 PST
Received: from JUNCO.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 92747; Tue 13-Jan-87 14:23:50 EST
Date: Tue, 13 Jan 87 14:23 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Issues for the CLOS committee to start focussing on
To: Bobrow.pa@Xerox.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM,
Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870113-103835-6035@Xerox>
Message-ID: <870113142321.8.SKEENE@JUNCO.SCRC.Symbolics.COM>
Line-fold: No
Date: 13 Jan 87 10:38 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Date: 8 Jan 87 23:48 PST From: Danny Bobrow
<Bobrow.pa@Xerox.COM>
Class variables. (Discussion is ongoing, probably almost
finished)
What is your belief about the state of this. I made a
detailed suggestion last.
Danny, I assume you're asking me, since I was the TO:
recipient. My belief is that it hasn't converged yet, but is close.
I don't think I've read your detailed suggestion carefully yet.
This issue isn't one of the next three on my priority list; if
you'd rather I thought about this first, though, let me know and I
will.
Sonya said she would write up what I had suggested in English, and we
can go from there. (Right Sonya?)
danny
Right, Danny. I've written up a draft of this, and given it to Dave
for sanity checking and to get answers to some questions that came up.
We'll probably have it ready for public viewing sometime today or
tomorrow.
∂15-Jan-87 0837 skeene@STONY-BROOK.SCRC.Symbolics.COM draft on inheritance of slots and defclass options
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 15 Jan 87 08:33:06 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 44527; Thu 15-Jan-87 11:31:35 EST
Date: Thu, 15 Jan 87 11:31 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: draft on inheritance of slots and defclass options
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870115113125.4.SKEENE@JUNCO.SCRC.Symbolics.COM>
Most of the following came from Danny's message of awhile back. We
changed the inheritance behavior of :type so that the compiler could
do some optimization based on the :type option given in a local DEFCLASS
description.
This draft seems long for the subject matter it's covering, but I think
it's worth spelling out all the possibilities. As soon as people read
this and give comments about it, I'll edit it into the document.
------------------------------------------------
INHERITANCE
A class inherits methods, slots, and some DEFCLASS options from all of
its superclasses. However, the class can choose to override an
inherited method, slot, or DEFCLASS option. This section describes what
is inherited from superclasses, and how a class can override an aspect
of inherited behavior.
INHERITANCE OF METHODS
Methods are inherited by subclasses. That is, a method provided by a
class is applicable for use on instances of any subclass of that
class. In some cases, an inherited method can be shadowed by providing
a method for a more specific class. When standard method combination
is used, the primary method can be shadowed by a method on a more
specific class. (However, if the more specific method uses
CALL-NEXT-METHOD, the next most specific primary method is called.)
The inheritance of methods acts the same way regardless of whether the
method was created using DEFMETHOD or by using one of the DEFCLASS
options that cause methods to be generated automatically (for reading or
accessing the value of a slot).
INHERITANCE OF SLOTS
In general, slots are inherited by subclasses. An instance has at most
one slot by any given name accessible to it. The inheritance of slots
depends on whether the inherited slot is allocated by :class or
:instance, and whether the :allocation slot option is given in the local
slot-description. There are several different cases.
1. In the simplest case, a class does not provide a local description
of a slot with the same name as a slot provided by its superclass. If
it is an :instance slot, the subclass allocates storage for it in each
instance. If it is a :class slot, the allocation of the slot is done by
the superclass, and that single slot is accessible by instances of both
the superclass and the subclass.
2. Whenever a class specifies :allocation :class, a new :class slot is
created, and any slot with that name provided by a superclass is not
accessible to instances of this class.
3. Whenever a class specifies :allocation :none for a slot, no slot
with that name is accessible to instances of this class. Thus, the
:allocation :none option allows for subtractive inheritance; a class can
specify :allocation :none to prevent access to a slot supplied by a
superclass.
4. Whenever a class provides a local description of an :instance slot,
and its superclass provides a description of a :class slot with
the same name, only the :instance slot that was described locally
is accessible to the subclass. Only the :class slot is accessible
instances of the superclass. (Note that the DEFCLASS default :allocation
is :instance, so a slot description is treated as an :instance slot
if the :allocation option is not explicitly supplied.)
5. Whenever a class provides a local description of an :instance slot,
and its superclass also provided a description of an :instance slot with
the same name, the effect of the local slot description is to override
or alter some of the inherited characteristics of the slot, such as its
:initform or :type options. (The inheritance behavior of each DEFCLASS
option is described further on in this section.)
The wording of the above cases mentions one subclass and one superclass,
but a class often has more than one superclass. The class precedence
order is used to determine how the slots are inherited. When a class is
defined, the slots that it will be able to access are determined by
considering each local slot-description, and the description of each
slot that is given by the most specific superclass in the class
precedence list. The examples further on in this section should
clarify this behavior.
INHERITANCE OF DEFCLASS OPTIONS
:ACCESSOR -- This option is not inherited; subclasses do not
automatically generate methods for accessing a slot unless the :ACCESSOR
prefix is specified in the local description. However, a subclass does
inherit the methods generated by this option, in the sense that the
methods are applicable for instances of the subclass. Because these
methods are primary methods, when standard method combination is used
the subclass can shadow the inherited methods by providing more specific
methods, either by using the :ACCESSOR option or using DEFMETHOD. The
type of inheritance described here also applies to the methods generated
by the :reader, :accessor-prefix, and :reader-prefix options.
:READER -- This slot option is not inherited; see the description of the
:accessor slot-option.
:ALLOCATION -- This option is not inherited by subclasses. However, if
a local slot description is given for a slot with the same name as a
slot provided by a superclass, this option affects the inheritance of
the slot. The semantics of slot inheritance and the :allocation option
are described above.
:INITFORM -- The :initform option is inherited, and can be overridden in
a straightforward way. In the case of an inherited :instance slot, if
the :initform option is given in a local description, the local
:initform completely overrides the inherited :initform.
:TYPE -- The :TYPE option is inherited as follows. When a class is
being defined, the slot descriptions of all of its superclasses
(including itself) are considered, regardless of the allocation of the
slot. The type of the value of the slot is constrained to satisfy all of
the type constraints given in the descriptions of each of its
superclasses, including itself. That is, if T1, T2 and so on are the
type constraints given by the class and all of its superclasses, the
value of the slot must satisfy (typep value '(and T1 T2 T3...). [This
inheritance behavior allows a compiler to optimize on the basis of the
:TYPE option in the DEFCLASS form. Some operations can be improved,
when the slot directly is involved in an arithmetic expression, such as
being able to emit the machine addition instruction with only overflow
checking.]
CLASS OPTIONS:
:ACCESSOR-PREFIX -- This slot option is not inherited; see the
description of the :ACCESSOR slot-option.
:READER-PREFIX -- This slot option is not inherited; see the description
of the :ACCESSOR slot-option.
:CONSTRUCTOR -- This option has no effect on subclasses; it is not
inherited.
:DOCUMENTATION -- This option has no effect on subclasses; it is not
inherited.
:METACLASS -- This option has no effect on subclasses; it is not
inherited.
EXAMPLES OF INHERITANCE:
(defclass C1 () ((S1 :initform 5.4 :type number)
(S2 :allocation :class))
(defclass C2 (C1) ((S1 :initform 5 :type integer)
(S2 :allocation :instance)
(S3 :accessor C2-S3))
:reader-prefix C2-)
(defclass C3 (C2) ((S2 :allocation :none)))
(defclass C4 (C3 C2) ())
C1 has an :instance slot named S1, whose default initial value is 5.4,
and whose value is constrained to be a number. C1 also has a :class
slot named S2.
C2 has access to an :instance slot named S1, whose default initial value
is 5, and whose value is constrained to satisfy (typep value '(AND
integer number)). C2 has access to two :instance slots, named S1 and
S2. C2 has methods defined for reading the value
of its slots; these methods are for the generic functions named: C2-S1,
C2-S2, and C2-S3. There is also a SETF method for use with C2-S3.
C3 has access to an :instance slot named S1, whose default initial value
is 5, and whose value is constrained to satisfy (typep value '(AND
integer number)). C3 also has access to a slot named S3. C3 has
methods applicable for reading the value of the slots S1, S2, and S3.
Note that although C3 has a method for reading the value of slot S2, it
does not have access to that slot, so using the method would result in
an error.
The class precedence order for C4 is: (C4 C3 C2 C1). Because C3 comes
before C2 in the precedence order, class C4 does not have access to slot
S2.
∂15-Jan-87 1514 Gregor.pa@Xerox.COM Re: Issues for the CLOS committee to start focussing on
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Jan 87 15:11:28 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 15 JAN 87 14:03:16 PST
Date: 15 Jan 87 13:05 PST
From: Gregor.pa@Xerox.COM
Subject: Re: Issues for the CLOS committee to start focussing on
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 11 Jan 87 22:22 PST
To: Bobrow.pa@Xerox.COM
cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870115-140316-1301@Xerox>
Date: 11 Jan 87 22:22 PST
From: Danny Bobrow <Bobrow.pa>
The name for standard method combination in the concepts document,
and
elsewhere
No, it should be some word which includes default, maybe even just
default. This is to be consistent with default-class, default-method
etc.
∂15-Jan-87 1713 Masinter.pa@Xerox.COM Re: draft on inheritance of slots and defclass options
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Jan 87 17:13:39 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 15 JAN 87 15:57:17 PST
Date: 15 Jan 87 16:00 PST
From: Masinter.pa@Xerox.COM
Subject: Re: draft on inheritance of slots and defclass options
In-reply-to: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 15 Jan 87 11:31 EST
To: skeene@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870115-155717-1583@Xerox>
I liked the phrasing
"In general, xs are inherited by subclasses; that is, ..."
You used it
"Methods are inherited by subclasses. That is, a method provided by a
class is applicable ..."
I'd like it
INHERITANCE OF SLOTS
In general, slots are inherited by subclasses. That is, slots defined in
a class are usually also slots in any subclass of that class. The
inheritance of slots depends on ....
- - - - - - - -
I was confused by the organization of defclass options because the
initial set of options were really slot options within a defclass rather
than defclass options.
I see no advantage in spelling out :READER -- ... ;see :ACCESSOR instead
of saying
:ACCESSOR, :READER -- These options are not inherited; that is,
subclasses do not ...
-----
Your section says EXAMPLES OF INHERITANCE yet it is a single example.
Rather than packing them all into a single example, it would be much
clearer to give separate examples.
∂16-Jan-87 0748 skeene@STONY-BROOK.SCRC.Symbolics.COM Re: draft on inheritance of slots and defclass options
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 16 Jan 87 07:48:32 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 45061; Fri 16-Jan-87 10:44:52 EST
Date: Fri, 16 Jan 87 10:44 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: draft on inheritance of slots and defclass options
To: Masinter.pa@Xerox.COM
cc: skeene@STONY-BROOK.SCRC.Symbolics.COM,
common-lisp-object-system@sail.stanford.edu
In-Reply-To: <870115-155717-1583@Xerox>
Message-ID: <870116104441.0.SKEENE@JUNCO.SCRC.Symbolics.COM>
Line-fold: No
Date: 15 Jan 87 16:00 PST
From: Masinter.pa@Xerox.COM
Thanks for replying so quickly. This morning I made most of the
changes you suggested, and will write out the concepts file today.
I liked the phrasing
"In general, xs are inherited by subclasses; that is, ..."
You used it
"Methods are inherited by subclasses. That is, a method provided by a
class is applicable ..."
I'd like it
INHERITANCE OF SLOTS
In general, slots are inherited by subclasses. That is, slots defined in
a class are usually also slots in any subclass of that class. The
inheritance of slots depends on ....
I made this wording change.
- - - - - - - -
I was confused by the organization of defclass options because the
initial set of options were really slot options within a defclass rather
than defclass options.
Right, I forgot to put in a subheading called "Inheritance of
DEFCLASS Slot-options". That header makes the organization much clearer.
The subsection "Inheritance of DEFCLASS Options" is divided into two
pieces: one for the slot-options and one for the class-options.
I see no advantage in spelling out :READER -- ... ;see :ACCESSOR instead
of saying
:ACCESSOR, :READER -- These options are not inherited; that is,
subclasses do not ...
I could do it that way, but I prefer to list each option separately. If the
reader-person wanted to find out how the :READER option was inherited, it's
easier to find it if each option is separated out from the text. Also,
the way I did it, I can refer to the :ACCESSOR slot-option in the text for the
:READER-PREFIX and :ACCESSOR-PREFIX class-options, rather than repeating that
paragraph again in the class-options part.
-----
Your section says EXAMPLES OF INHERITANCE yet it is a single example.
Rather than packing them all into a single example, it would be much
clearer to give separate examples.
You could call it a single example, but it illustrates many of the
inheritance concepts. One advantage of the way its done now is brevity
(not usually my strong point as a writer), so I hesitate to make this
section even longer. But I'll play around with separating each concept
into its own example and see if that works better.
∂16-Jan-87 0821 skeene@STONY-BROOK.SCRC.Symbolics.COM new versions of files
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 16 Jan 87 08:21:05 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 45087; Fri 16-Jan-87 11:19:34 EST
Date: Fri, 16 Jan 87 11:18 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: new versions of files
To: lgd@stanford.sail.edu, rpg@stanford.sail.edu
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870116111824.2.SKEENE@JUNCO.SCRC.Symbolics.COM>
I wrote new versions of concepts and functions.
Functions.tex: Edited the method combination functions.
Edited the :method-combination options to defgeneric-options,
defgeneric-options-setf, and make-generic-function.
Edited the defclass :initform option to talk
about when it is evaluated, according to the mail about it.
Concepts.tex: Put in a new Inheritance chapter that
talks about inheritance of slots, methods (slightly), and
defclass options. I included Larry Masinter's comments.
Terminology changes in both files:
Changed occurrences of "daemon" method combination type to
"standard".
Changed occurrences of "unqualified method" to "primary method"
where it was appropriate.
I think that's all I did. I'll hand control of these files
back to you two now. I'm going to work on updating the Glossary
to use the new terminology.
∂19-Jan-87 2142 Moon@MEAD.SCRC.Symbolics.COM change-class and class redefinition
Received: from [192.10.41.234] by SAIL.STANFORD.EDU with TCP; 19 Jan 87 21:42:16 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by MEAD.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 44265; Mon 19-Jan-87 23:56:22 EST
Date: Mon, 19 Jan 87 23:56 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: change-class and class redefinition
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
References: <861020222040.5.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<861021103246.4.GREGOR@AVALON.isl.parc.xerox.com>,
<861117153938.3.GREGOR@AVALON.isl.parc.xerox.com>,
<861212100117.4.SKEENE@JUNCO.SCRC.Symbolics.COM>,
<861217234009.5.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<861228213807.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870119235610.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Here's what I have so far on the subject, culled from the referenced
messages plus my own head. This is unfinished, but it seems worth
putting it out for comments in its current condition. This message
won't get out of the building until the snow stops, but I can hope
that it will get to SU-AI sometime Tuesday morning.
Class changing writeup
First we will discuss CHANGE-CLASS. What happens when DEFCLASS redefines
a class is discussed later.
Changes to the change-class writeup:
In the arguments field, it isn't really true that instance can be any
object. The arguments field should allude to the restriction discussed
in the remarks field.
Gregor's example of converting between rectangular and polar coordinates,
mailed out 17 Nov 86, could be inserted into the examples field.
All other fields are okay except the remarks field. Replace it according
to the following:
(1) Not all objects can change their class
If C1 and C2 are classes that were defined by DEFCLASS, without using the
:METACLASS option in either case, and X is an instance of class C1, X's
class can be changed to C2. This is the only case for which this standard
guarantees that CHANGE-CLASS is allowed. Both before and after the call
to CHANGE-CLASS, X's metaclass is the default metaclass.
Whether CHANGE-CLASS is allowed for instances of a different metaclass
than the default one is up to the implementor of the particular metaclass.
The Metaclass Protocol document will describe how to control this.
Implementations can choose to support CHANGE-CLASS in additional cases if
they desire. For example, this standard does not require CHANGE-CLASS to
or from a standard-type-class to be supported, however it is valid for an
implementation to support it for some standard-type-classes. In any case
where CHANGE-CLASS is not allowed, it signals an error.
(2) Changing the metaclass
Whether CHANGE-CLASS is allowed to change an object's metaclass is up to
the implementors of the two particular metaclasses. The Metaclass Protocol
document will describe how to control this.
(3) Preservation of slot values
CHANGE-CLASS preserves the values of slots that are common between the old
and new classes, and initializes any remaining slots of the new class.
Specifically, for each :ALLOCATION :INSTANCE slot of the new class, if
there is a slot by the same name in the old class (with any :ALLOCATION
other than :NONE), the slot's value is preserved. This means that if the
slot has a value, the value returned by SLOT-VALUE after the CHANGE-CLASS
is EQL to the value returned by SLOT-VALUE before the CHANGE-CLASS, while
if the slot is uninitialized, it remains uninitialized and no error is
signalled.
Each :ALLOCATION :INSTANCE slot of the new class with no slot by the same
name in the old class is initialized to the value of its :INITFORM, or
remains uninitialized if there is no :INITFORM. This is the same as the
initialization done by MAKE-INSTANCE, except that no initialization methods
are invoked and no MAKE-INSTANCE initialization arguments are present.
The value of each :ALLOCATION :INSTANCE slot of the old class with no slot
by the same name in the new class is discarded.
(4) CLASS-CHANGED methods
[CLASS-CHANGED was the best name I could think of off-hand. In Flavors
this is named TRANSFORM-INSTANCE. In CommonLoops it is named
CHANGE-CLASS-INTERNAL, I believe.]
After completing all other actions, CHANGE-CLASS invokes the generic
function CLASS-CHANGED on two arguments, named previous and current,
representing two views of the instance. The returned value is ignored.
The default method for CLASS-CHANGED does nothing, but programmers can
define their own methods to do such things as initialize new slots
differently from MAKE-INSTANCE or copy information from slots that only
exist in the old class into differently-named slots in the new class.
The first argument, previous, is an instance of the old class created to
hold the old slot values temporarily. It has dynamic extent, thus it is an
error to reference previous in any way after CLASS-CHANGED returns. The
typical use of previous is as an argument for SLOT-VALUE, WITH-SLOTS, or an
accessor generic function, to extract old slot values. In fact any function,
generic or not, can receive previous as an argument; thus information
about previous that is not directly stored in slots can be extracted.
The second argument, current, is the instance given as the first argument
to CHANGE-CLASS. At the time CLASS-CHANGED is called it has been fully
converted to the new class.
CLASS-CHANGED methods can, of course, make the slot value preservation
behavior of CHANGE-CLASS different from that described earlier.
(5) Restrictions on when CHANGE-CLASS can be called
[this section needs work]
There are two semantic difficulties associated with CHANGE-CLASS. The
first problem occurs if an object's class is changed while a generic
function is executing with that object as an argument. If the object's
class is used for method selection, the currently executing method might
now be the wrong method, not applicable to the object's new class. No
known \CLOS\ implementation can undo the effects of executing the wrong
method and cause the right method to be executed instead, so the wrong
method simply continues executing. When a particular generic function
invocation invokes multiple methods because of method combination or
CALL-NEXT-METHOD, an implementation is permitted, but not required, to
decide on the set of methods to be invoked at the beginning of the generic
function invocation. Thus the set of methods invoked after the class has
been changed is implementation-dependent and not defined by this standard.
The second problem concerns optimization of slot access. This standard
permits, but does not require, an implementation to compile WITH-SLOTS in
an early-binding style. [Does this apply to explicit calls to SLOT-VALUE
inside methods also?] This means that the determination of how slots are
to be accessed (their memory address and whether a method needs to be
invoked) can be done when the actual slot access occurs, when the
WITH-SLOTS is entered, when the method containing the WITH-SLOTS is
entered, or when the generic function that invokes the method is called.
This implementation freedom is a concession to efficiency, which is judged
more important than the semantics of CHANGE-CLASS. If the class is changed
after the determination of how slots are to be accessed and before the
actual slot access, the results are undefined. This means that if a method
changes the class of an argument, that method, and any other methods invoked
by the same generic function invocation, must not access slots of that
argument afterwards.
[Another way to explain this is to speak of an activation record corresponding
to the lexical context in which the class of an object is known (e.g. because
of a parameter specializer or because of a method discrimination), and
to say that changing the class of the object puts the activation record
into "a wierd state".]
Note that the call to CHANGE-CLASS that causes semantic difficulties might
not be lexically visible. CHANGE-CLASS could be called by a function that
is called by a method. All that matters is that the class is changed while
the method is dynamically active.
Note that in multi-process systems, the semantic difficulties discussed
above occur even when the generic function invocation is in one process and
CHANGE-CLASS is called in a different process.
[The following comes from Flavors. I believe all implementations should
be able to support this, but if some implementation has great difficulty
implementing this we could relax the standard.]
The second semantic difficulty occurs when CHANGE-CLASS changes the
arrangement in storage of the slots. By special dispensation, this
difficulty never occurs for the implicit call to CHANGE-CLASS that
occurs when a class is redefined. In addition, the programmer can
avoid this difficulty by obeying the following rules:
If the old and new classes have the same slots, and inherit them from the
same superclasses, then their arrangement in storage will be the same.
This can be accomplished by using mixin classes that do not define any
instance variables of their own, and using CHANGE-CLASS only to change
which of these mixins are included. A more complex solution ensures only
that the slots that are actually accessed remain in the same arrangement
in storage. These slots must be inherited from common superclasses. The
old and new classes can have additional slots supplied by superclasses
earlier in the precedence list than them. [This is not explained very
well, the idea is that slot allocation is from the least-specific-class
first, i.e. in reverse order of precedence, so if only slots in the common
tail of the class precedence list are accessed, it's guaranteed that those
slots won't have changed their arrangement in storage.]
===============
Next we discuss what happens when DEFCLASS redefines a class in a way
that changes the set of slots in an instance, or their order in storage.
Note that the affected class might not be the one whose DEFCLASS was
re-evaluated; it could be a subclass of that class.
[Part of the remarks field of DEFCLASS will be replaced by this.]
Redefining a class modifies the existing class object to reflect the new
class definition; it never creates a new class object for the class. All
methods applicable to the class remain, except for methods created by the
:accessor, :reader, :accessor-prefix, and :reader-prefix options when those
options have been changed in the DEFCLASS form.
Redefining a class in a way that changes the set of slots in an instance,
or their order in storage, also creates an [italics] obsolete class object.
This class has no name. The only instances of this class that can ever
exist are those created as the [italics] previous argument to a CLASS-CHANGED
method. All methods applicable to the class before redefinition, including
methods created by the :accessor, :reader, :accessor-prefix, and
:reader-prefix options, become applicable to the obsolete class also. This
allows a CLASS-CHANGED method to extract information from its [italics]
previous argument. [Are future changes in methods reflected to the
obsolete class? Deal with additions, deletions, and redefinitions
separately? Should the standard define this?]
When an instance of a class that has been redefined is accessed, the
instance is automatically updated to the new class definition. "Accessed"
means calling a generic function with the instance as an argument that is
used for method selection, calling one of the functions CLASS-OF,
SLOT-VALUE, TYPE-OF, TYPEP [maybe others?]. Updating an instance does
not change its identity as defined by the EQ function; it changes the class
and slots of that particular instance; it does not create a new instance.
Whether updating an instance consumes storage is implementation-dependent.
Updating an instance calls CHANGE-CLASS, whose behavior and programmability
using CLASS-CHANGED methods was described earlier.
[Still to be defined: how if you redefine a class several times, you can
create CLASS-CHANGED methods that perform updates from one particular
version of the class to another particular version. The simplest
answer is that you can't, instead you have to write your methods to
work for any version of the class.]
[What about addition/removal of class variables?]
∂20-Jan-87 1010 DLW@ALDERAAN.SCRC.Symbolics.COM change-class and class redefinition
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 20 Jan 87 10:10:03 PST
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 40834; Tue 20-Jan-87 10:43:48 EST
Date: Tue, 20 Jan 87 10:42 EST
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: change-class and class redefinition
To: Moon@STONY-BROOK.SCRC.Symbolics.COM,
Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870119235610.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870120104211.2.DLW@CHICOPEE.SCRC.Symbolics.COM>
Date: Mon, 19 Jan 87 23:56 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
[CLASS-CHANGED was the best name I could think of off-hand. In Flavors
this is named TRANSFORM-INSTANCE. In CommonLoops it is named
CHANGE-CLASS-INTERNAL, I believe.]
CLASS-CHANGED is a good name. This name makes it clear that you aren't
supposed to call this function yourself; you're only supposed to handle
it. (I wish there were a term for that kind of generic function.) The
other two names are both imperative, and so don't make it clear.
You have to specify what sort of method combination is used for
CHANGE-CLASS. Presumably the default one, but it should be specified in
case there's any question.
(5) Restrictions on when CHANGE-CLASS can be called
Redefining a class modifies the existing class object to reflect the new
class definition; it never creates a new class object for the class. All
methods applicable to the class remain, except for methods created by the
:accessor, :reader, :accessor-prefix, and :reader-prefix options when those
options have been changed in the DEFCLASS form.
Do accessors that used to be defined, but are not now defined, actually
get undefined (fmakunbound'ed)?
∂20-Jan-87 1224 Bobrow.pa@Xerox.COM New version of define-method-combination
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 20 Jan 87 12:20:45 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 20 JAN 87 12:21:11 PST
Date: 20 Jan 87 12:11 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: New version of define-method-combination
To: common-lisp-object-system@SAIL.STANFORD.EDU
cc: Bobrow.pa@Xerox.COM
Message-ID: <870120-122111-2214@Xerox>
The following is an alternate version of define-method-combination.
It has the following properties:
1) There is only one define-method-combination form. It allows easy
support of around methods, and supports error checking. Defining simple
combinations is easy and concise.
2) There is no lambda-list. It also omits the keyword :order from the
method specifier. defgeneric-options is extended to store parameters
in the generic function. This can be used to support features like
reversed order for <and> combination if desired.
3) It is syntactically distinguishable from the current Flavors
version of define-method-combination, and hence allows backwards
compatiblity.
4) It uses the keyword :call-next-method instead of :around in
make-method-call. This eliminates confusion with respect to use of
this keyword with primary methods, and with respect to the new :around
keyword in method-combination options used to support around methods.
Thus
(make-method-call primary :around t)
becomes
(make-method-call primary :call-next-method t)
This renaming needs to be carried through to the functi
chapter.
Text that looks similar to that in the concep chapter was in fact taken
from there, and no changes were made in most paragraphs.
I am recommending that we include this instead of the
current version in concep.
*** Extension to defgeneric-options
defgeneric-options
{\bf :method-combination }
The list that is cdr of the option form is stored
in the generic-function object in the slot
{\it method-combination\/}.
Example:
(:method-combination and :most-specific-last)
stores {\it (and :most-specific-last)\/} in the slot
{\it method-combination\/}.
The body of compute-effective-method can get this information
from the generic-function using the slot-accessor.
***
*** Alternate version of define-method-combination***
\beginSection{Declarative Method Combination}
\beginsubSection{Defining Form for Method Combination}
The programmer can define new forms of method combination using the {\bf
define-method-combination} macro. This allows customization of step~3
of the method combination procedure. The body of {\bf
define-method-combination\/} used resembles {\bf defmacro\/} in that the
body is an expression that computes a Lisp form, usually using
backquote. Thus, an arbitrary combination of methods can be
constructed.
%The following syntax expressions need to be converted to TEX
(DEFINE-METHOD-COMBINATION name [macro]
({method-group-specifier}+ )
[({method-combination-option}*)]
{form}*)
{method-group-specifier}:= (variable { {qualifier-pattern}+ | predicate}
{keyword argument}*)
{method-combination-option} :=combination-keyword value
{\it name\/} is a symbol, usable as a name for this in
the {\bf :method-combination}
option to {\bf defgeneric-options} or {\bf defgeneric-options-setf}.
By convention, non-keyword, non-{\bf nil} symbols are usually used.
{\bf method-group specifiers\/}
A list of method-group specifiers follows the name.
Each specifier selects a subset
of the applicable methods to play a particular role, either by matching
their qualifiers against some patterns or by testing their qualifiers
with
a predicate. These method-group specifiers define all method qualifiers
that can be used with this type of method combination. If an applicable
method does not fall into any method-group, the system reports the error
that the method is not appropriate for the kind of method-combination
being
used.
Each method-group specifier names a variable. During the execution of
the
body forms, the variable is bound to a list of the methods in the
method-group, in most-specific-first order.
A qualifier-pattern is a list or the symbol {\bf *}. A method matches a
qualifier-pattern if the method's list of qualifiers is {\bf equal} to
the
qualifier-pattern, except that the symbol {\bf *} in a qualifier-pattern
matches anything. Thus a qualifier-pattern can be the empty list {\bf
()}
(which matches primary methods, which are always unqualified),
the symbol {\bf *} (which matches all
methods), a true list (which matches methods with the same number of
qualifiers as the length of the list, when each qualifier matches the
corresponding list element), or a dotted list that ends in the symbol
{\bf *} (the {\bf *} matches any number of additional qualifiers).
(True lists are non-dotted lists, as defined in {\it Common Lisp: The
Language\/}.)
Each applicable method is tested against the qualifier-patterns and
predicates in left-to-right order. As soon as a qualifier-pattern
matches
or a predicate returns true, the method becomes a member of the
corresponding method-group and no further tests are made. Thus if a
method
could be a member of more than one method-group, it joins only the first
such group. If a method-group has more than one qualifier-pattern, a
method need only satisfy one of the qualifier-patterns to be a member of
the group.
The name of a predicate function can appear in place of the
qualifier-patterns in a method-group specifier. The predicate is called
for each method that has not been assigned to an earlier method-group,
with
one argument, the method's qualifier list. The predicate should return
true if the method should be a member of the method-group. A predicate
is
distinguishable from a qualifier-pattern because it is a symbol other
than
{\bf nil} or {\bf *}.
Method-group specifiers can have keyword options after the
qualifier-patterns or predicate. Keyword options are distinguishable
from
additional qualifier patterns because they are not lists nor the symbol
{\bf *}. The keyword options are:
\def\numhangsize{60pt}
\numitem{{\bf :required} {\it boolean\/}} \break
If the argument is true (not {\bf nil}), and the method-group is empty
(that is, no applicable methods match the qualifier-patterns or satisfy
the
predicate), an error is signalled. This keyword option is a convenience
and does not add any expressive power. It is provided so that
programmers
are not tempted to omit error checking.
If {\bf :required} is not specified, it defaults to {\bf nil}.
The argument {\it boolean\/} is not evaluated.
\numitem{{\bf :description} {\it format-string\/}} \break
Programming environment tools use
% TEX won't let me use #' in the next line
{\bf (apply (function format) stream {\it format-string\/}
(method-qualifiers {\it method\/}))}
to print a concise description of a method's role (one or two
words). This keyword option allows the description of a method
qualifier to be defined in the same module that defines the
semantic meaning of the method qualifier. In most cases {\it
format-string\/} will not contain any format directives, but they
are available for generality. If {\bf :description} is not
specified, a default description is generated based on the
variable name, the qualifier patterns, and whether this
method-group includes the primary methods. The argument {\it
format-string\/} is not evaluated.
\def\numhangsize{25pt}
Individual implementations might support other keyword options.
Therefore it is required that implementations signal an error if
they observe a keyword option that is not implemented locally.
{\bf method-combination} options.
The list of method-combination options is optional, and is
distinguished from a form because it starts with a keyword.
The keyword options supported are:
{\bf :documentation} {\it string\/} documents the method-combination
type.
{\bf :around} {\it boolean\/}
If the argument is true (not {\bf nil}),
then the form returned by the body of define-method-combination
is augmented to support :around methods. See examples below.
This keyword option is a convenience and does not add any
expressive power. It is provided so that programmers are not
tempted to omit support for :around methods. Methods matching
(:around) are extracted first from the list of applicable
methods. If {\bf :around} is not specified, it defaults to
{\bf nil}. The argument {\it boolean\/} is not evaluated.
\def\numhangsize{25pt}
Individual implementations might support other method-combination
option; these must be keywords to ensure unambiguous interpretation.
Therefore it is required that all implementations signal an error if
they observe a keyword option that is not implemented locally.
The use of method-group specifiers provides a convenient syntax for the
cliched code that has to be written for every kind of method
combination,
to select methods, divide them among the possible roles, and perform the
necessary error checking. It is possible to perform further filtering
of
methods in the body forms, using normal list-processing operations and
the
functions {\bf method-qualifiers} and {\bf invalid-method-error}. It is
permissible to {\bf setq} the variables named in the method-group
specifiers and to bind additional variables. It is also possible to
bypass
the method-group specifier mechanism and do everything in the body
forms.
This is accomplished by writing a single method group with {\bf *} as
its
only qualifier-pattern; the variable is then bound to a list of all of
the
applicable methods, in most-specific-first order.
The body {\it forms\/} compute and return the Lisp form that specifies
how
the methods are combined, that is, the effective method.
The body of {\bf define-method-combination} resembles the body of
{\bf defmacro} and uses backquote in a similar way.
The function {\bf make-method-call} must be used in constructing the
Lisp form; it hides the implementation-dependent details of how
methods are called. Programmers always use {\bf make-method-call} to
translate from the lists of method objects produced by the method-group
specifiers to Lisp forms that invoke those methods.
Erroneous conditions detected by the body should be reported with
{\bf method-combination-error} or
{\bf invalid-method-error}; these functions
add any necessary contextual information to the error message and will
use
the condition signalling system when and if it is adopted into Common
Lisp.
The body {\it forms\/} are evaluated inside of the bindings of the
compute-effective-method lambda-list and method-group specifiers. The
variable {\it generic-function\/} is available in the body forms of the
combination definition. Since there are no declarations except inside a
user
form, declarations cannot effect bindings of variables in the
lambda-list
(e.g {\it generic-function\/} or any method-group variables.
The code may use any information obtainable from the particular
generic-function object.
The functions {\bf make-method-call}, {\bf method-combination-error},
and
{\bf invalid-method-error} can be called from the body {\it forms\/}, or
from functions called by the body {\it forms\/}. The action of these
three
functions can depend on dynamic variables bound by the object system
before
calling the method-combination function. These variables might contain
the
parameter list of the effective method or other implementation-dependent
information.
\endsubSection%{Defining Form for Method Combination}
\beginsubSection{Examples of define-method-combination}
%These examples could be put in the EXAMPLES field of the
DEFINE-METHOD-COMBINATION
%function description. I think it's better to put them into the
Concepts
%chapter and cross-reference them from the function description.
\screen!
;The default method-combination, the hard way
(define-method-combination standard
((around (:around))
(before (:before))
(primary ())
(after (:after)))
(unless primary
(method-combination-error "A primary method is required."))
(make-method-call `(,@around
(multiple-value-prog2
,(make-method-call before)
,(make-method-call primary :call-next-method t)
,(make-method-call (reverse after))))
:call-next-method t))
;The default method-combination using keyword options
(define-method-combination standard
((before (:before))
(primary () :required t)
(after (:after)))
(:around t)
(multiple-value-prog2
,(make-method-call before)
,(make-method-call primary :call-next-method t)
,(make-method-call (reverse after))))
;A simple way to try several methods until one returns non-nil
(define-method-combination and
((methods () (:and)))
(make-method-call methods :operator 'and))
;A more complete version of the preceding, adding around methods
and checking that there is a primary method.
(define-method-combination and
((primary () (:and) :required t))
(:around t :description "First method returning non-NIL"))
(make-method-call primary :operator 'and
:identity-with-one-argument t))
;Order methods by positive integer qualifiers
(define-method-combination example-method-combination
((methods positive-integer-qualifier-p))
(:around t)
(make-method-call (stable-sort methods #'<
:key #'(lambda (method)
(first (method-qualifiers method))))))
(defun positive-integer-qualifier-p (method-qualifiers)
(and (= (list-length method-qualifiers) 1)
(typep (first method-qualifiers) '(integer 0 *))))
\label Using Parameter Passing
;Using method-combination parameters,
;one can obtain parametric ordering for {\it and\/} combination.
(define-method-combination and
((primary () (:and) :required t))
(:around t))
(when (apply order-parameter
(cdr (method-combination generic-function)))
(setq primary (reverse primary)))
(make-method-call primary :operator 'and
:identity-with-one-argument t))
(defun order-parameter (&optional (order :most-specific-first))
(case order
(:most-specific-first ())
(:most-specific-last t)
(otherwise (method-combination-error ''~S is an invalid order.~@
:most-specific-first and :most-specific-last are the possible
values.''
order)))
\endscreen!
\endsubSection%{Examples of define-method-combination}
\endSection%{Declarative Method Combination}
*** End Declarative Method combination***
∂20-Jan-87 1429 Gregor.pa@Xerox.COM Re: New version of define-method-combination
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 20 Jan 87 14:29:36 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 20 JAN 87 13:15:51 PST
Date: 20 Jan 87 13:15 PST
From: Gregor.pa@Xerox.COM
Subject: Re: New version of define-method-combination
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 20 Jan 87 12:11 PST
To: Bobrow.pa@Xerox.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870120-131551-2295@Xerox>
Here are my comments about Danny's proposed changes to method
combination. Some of these comments actually apply to Moon's last
revision also. Basically, I am commenting on the contents of Danny's
message as a whole without being too careful about where the particular
ideas came from.
I agree with the elimination of the simple form of
define-method-combination. I think this is a positive step towards
streamlining this part of the proposal.
I am not sure that method-group-specifier options are really needed. In
my most streamlining mood, I would suggest removing them. In a less
streamlining mood, I like the new :required method-group-specifier
option.
I like the new :around method-combination option. I think this will
make it easier for people to deal with :around methods. We might want
to think about changing the "sense" of this option, or changing the
default, so that aroundification happens by default.
I understand the motivation for allowing a predicate instead of the
templates. I think that motivation should be presented explicitly since
without it, the predicate seems like uneeded complexity.
I like changing the name of the :around keyword to make-method-call to
:call-next-method.
I don't really like the fact that information is communicated to
make-method-call using special variables. I thought having
make-method-call be a lexically bound function was much more elegant,
and much more in keeping with the lexically scoped way of doing things.
I don't really like method-combination-error and invalid-method-error.
They just add complexity to this part of the proposal to make up for the
fact that the error system has not been adopted yet. There are many
parts of the object system which want to signal special kinds of errors,
we don't have special functions for all of them. Perhaps what we should
do is assume the error system is going to be accepted (seems likely),
and then talk about what kind of error is signalled by each part of the
object system. This seems more reasonable than introducing a bunch of
error functions which will just have to be removed when the error
proposal is adopted, or worse yet supported as backwards compatibility
for life.
I still don't like calling the default kind of method combination
standard. I would prefer if we called it default, in fact, it might be
better to call it daemon-with-around or some other descriptive name.
What method combination types will we say are defined? There is a
definite package problem here. We should probably include some comment
on it in the spec. A user can't very well go and do
define-method-combination of lisp:and. If they do it "differently" they
could break the system or some other application. I think the examples
should be re-worked to show users defining method-combinations whose
names are symbols which are not in the lisp package.
∂21-Jan-87 1421 RPG standard-type-classes
To: common-lisp-object-system@SAIL.STANFORD.EDU
Referring to the design rationale chapter, there are comments about
what Common Lisp types should have classes. Some of the reasoning
for exclusion needs to be re-examined:
``Types too specific to be useful to put methods on: bit, keyword,
standard-char, string-char.''
Hm, I need more convincing than this.
``The type implies an implementation, not behavior.''
What's wrong with being able to write programs that reason about this?
If we had BUILT-IN-CLASS and STANDARD-TYPE-CLASS, we could distinguish
implementation details.
``Specification of the type is too vague.''
Included in this last case is FUNCTION. The rationale then says that
there is no function to make functions. Maybe so, but functions get made
and returned, and the user is quite aware, by design, of when it happens.
One can argue that a user might be aware of the fact that he is making
bignums, but he isn't required to be so aware. With functions you don't
start off with an array and when it becomes too complex it turns into
a function; there is nothing that gets turned into a function without
a user knowing it in the same way that a fixnun becomes a bignum.
I see no reason to further demean functions than they aleady are in
Common Lisp.
``No object can be an instance of this type: nil''
I want to call the class miasma a lattice to avoid having to
mention exceptions everywhere. A class with no instances is
reasonable for this. Also, Larry Masinter pointed out that
this could be a way to solve the unsupplied optionals problem.
An unsupplied optional ``matches'' a parameter specifier that
of this class. Maybe we don't want to call it NIL, but it's
the logical name for it.
I don't like the heuristic of only admitting types that have
makers or no single function that is a maker, because the
user simply wants to reason about the things that are, not
the things that came into being by some particular mode.
If it's bad to reason about the implementation technique, it's
almost as bad to reason about the history of a thing.
-rpg-
∂21-Jan-87 1632 kempf%hplabsc@hplabs.HP.COM Re: standard-type-classes
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 21 Jan 87 16:32:11 PST
Received: from hplabsc by hplabs.HP.COM ; Wed, 21 Jan 87 15:32:22 pst
Received: by hplabsc ; Wed, 21 Jan 87 15:25:43 pst
Date: Wed, 21 Jan 87 15:25:43 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8701212325.AA06103@hplabsc>
To: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: standard-type-classes
Yes, Gabrial has made a good point. Unless boolean classes
(i.e. classes which are `not' something) are to be admitted,
ATOM is probably a candidate not to have a class for. Most of
the others look like they could have classes though.
Jim Kempf kempf@hplabs.hp.com
∂21-Jan-87 1755 Gregor.pa@Xerox.COM Re: change-class and class redefinition
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Jan 87 17:55:30 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 21 JAN 87 13:32:59 PST
Date: 21 Jan 87 13:32 PST
From: Gregor.pa@Xerox.COM
Subject: Re: change-class and class redefinition
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 19 Jan 87 23:56 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870121-133259-194@Xerox>
The first part (1-4) of this looks good. I haven't yet had a chance to
think about the details of Restrictions on when CHANGE-CLASS can be
called or what DEFCLASS does. I do have some comments about the first
part though.
The most important comment I have is that I would like to have the
default method on class-changed be responsible for copying over slots.
I understand that the reason you put the responsibility for initializing
the slots of the "new" instance and copying the slots in the same place
(in change-class itself) is to prevent running the :initform of slots
which already existed in the "old" instance. Was this for efficiency or
because you preferred those semantics? If it was for semantics, here is
an alternate proposal:
Let change-class create a new-instance, but not call INITIALIZE on it.
Then it passes the "old" and "new" instances to class-changed.
class-changed can call initialize if it wants, or it can just copy old
slots or whatever.
My reasoning, is that I think things are more complicated when the rules
about when the various :initforms are run get complicated. This is
reflected in my initialization protocol which has the :initforms all
being run all at once.
I like the name class-changed. I also agree with DLW that we should
invent a term for generic-functions which you are not supposed to call
yourself. We will need this term in the meta-object protocol chapter.
The paragraph which says that previous has dynamic extent and also says
it can be passed around needs to be re-worked. What it says is exactly
right, its just that its confusing. It is very important to stress that
previous has dynamic extent.
∂21-Jan-87 1755 Bobrow.pa@Xerox.COM Small additional suggestion wrt Method-combination
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Jan 87 17:55:44 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 21 JAN 87 16:10:45 PST
Date: 21 Jan 87 16:12 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Small additional suggestion wrt Method-combination
To: Common-Lisp-Object-System@Sail.stanford.edu
cc: Bobrow.pa@Xerox.COM
Message-ID: <870121-161045-107@Xerox>
Because :operator and :call-next-method (nee :around) cannot both
appear, I suggest that the syntax of make-method-call be
(make-method-call method-list &optional
(operator 'progn)
(identity-with-one-argument (eq operator 'progn)))
Where if operator has the value :call-next-method, it has the same
effect as previously providing that argument with t as its value.
danny
∂21-Jan-87 2010 RPG Inheritance of Methods
To: common-lisp-object-system@SAIL.STANFORD.EDU
There is now a section in concepts about inheritance of methods. The
description of this inheritance makes most sense for ``classical''
methods; some would argue that those are the only methods for which this
description makes sense. CONCEPTS now does not contain the phrase ``classical
method,'' and this description does not jive with the section ``Method
Selection and Combination.'' Though this might have been a useful way to
conceptualize methods in the old days, I think it is outmoded, and we
plan to delete the subsection of ``Inheritance'' called ``Inheritance of
Methods.''
-rpg-
∂21-Jan-87 2200 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: change-class and class redefinition
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 21 Jan 87 21:59:45 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 48870; Thu 22-Jan-87 01:00:26 EST
Date: Thu, 22 Jan 87 00:57 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: change-class and class redefinition
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870121-133259-194@Xerox>
Message-ID: <870122005751.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 21 Jan 87 13:32 PST
From: Gregor.pa@Xerox.COM
....
The most important comment I have is that I would like to have the
default method on class-changed be responsible for copying over slots.
I understand that the reason you put the responsibility for initializing
the slots of the "new" instance and copying the slots in the same place
(in change-class itself) is to prevent running the :initform of slots
which already existed in the "old" instance. Was this for efficiency or
because you preferred those semantics?
It's for semantics. I believe it's important not to evaluate initforms
that aren't going to be used. However, that isn't the only reason, or
even the most important reason, why I proposed it the way I did. I want
the copying of the slots to be the responsibility of the implementation,
not of the programmer, for several reasons. Some of these reasons
involve implementation-dependent issues that are beyond the scope of the
standard, but that doesn't make the reasons any less valid. Here are
the reasons that apply to the Symbolics implementation. I expect there
are additional reasons in certain other implementations:
(1) Reading an uninitialized slot of course signals an error, so
copying the contents of a slot has to check for that.
(2) When a new piece of storage has to be allocated, the moving of the
slot contents from the old piece of storage to the new piece and the
redirection of the instance to its new piece of storage have to be
an atomic operation. Remember that the Symbolics implementation
is a multiple process implementation.
(3) Slots that contain special kinds of things, for instance logic
variables a la Prolog, may require special care to copy.
(4) I believe the current instance should be completely operable at
the time the class-changed methods are called, because the class-changed
methods may want to perform generic operations on the current instance,
as well as on the previous instance. The instance can't be completely
operable if the slot values aren't there yet.
However, this is missing the major point. I believe that "copying the
slots" is the wrong model of what is happening. A slot is a conceptual
entity, not a word of computer storage at a particular address. No slot
contents are being copied or changed. Some slots are being deleted,
some other slots are being newly created and therefore initialized, and
the rest of the slots remain unchanged. If a particular implementation
happens to work by moving the representation of a slot from location
1000 to location 1492, that's an implementation detail and not something
the programmer should see. At the level of abstraction that programmers
should deal with, a slot is a slot and nothing is being copied.
....
My reasoning, is that I think things are more complicated when the rules
about when the various :initforms are run get complicated. This is
reflected in my initialization protocol which has the :initforms all
being run all at once.
I don't think it's complicated. The rule is that newly created slots are
initialized to the value of their :initform. I'm assuming that the
:initforms for different slots are independent of each other and that
the language makes no commitment about the order in which :initforms
will be evaluated; are you assuming something different from that?
Differing assumptions might be the underlying reason why we're disagreeing.
If we can't finish change-class until we finish initialization I will go
back to working on initialization. I've been working on that, in between
interruptions, but don't have anything to report yet.
I like the name class-changed. I also agree with DLW that we should
invent a term for generic-functions which you are not supposed to call
yourself. We will need this term in the meta-object protocol chapter.
As an initial proposal, we could have "callable functions", "specializable
functions", and "functions that are both callable and specializable". If
they aren't specializable it's none of your business whether or not they
are generic, which is why I said "functions" instead of "generic functions."
Specializable means you can define methods for them. I don't claim this
is the best terminology in the world!
The paragraph which says that previous has dynamic extent and also says
it can be passed around needs to be re-worked. What it says is exactly
right, its just that its confusing. It is very important to stress that
previous has dynamic extent.
All of my English is pretty poor and will have to be gone over once we
have agreed on the facts.
∂21-Jan-87 2248 masinter.pa@Xerox.COM Re: standard-type-classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Jan 87 22:48:50 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 21 JAN 87 22:46:38 PST
From: masinter.pa@Xerox.COM
Date: 21 Jan 87 22:46:35 PST
Subject: Re: standard-type-classes
In-reply-to: RPG@SAIL.STANFORD.EDU's message of 21 Jan 87 14:21 PST
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870121-224638-1317@Xerox>
I'll try to dig out the old mail on this, as I remember going into it in
some detail in the past.
The reason for avoiding "bit" is similar to the reason for avoiding
(integer 0 1) and (integer -3 3) as "classes"... there's not much
special about one integer range over another, and arbitrary ranges give
the same problems as arbitrary types.
The reason for avoiding "keyword" is that it is (unfortunately) a
mutable property, in that it is possible to dynamically modify the home
package of a symbol (in a way that would not, for example, invoke
class-changed.)
The reason for avoiding standard-char is that it is again not a
significant "class" distinction. While it was interesting to use the
type system to categorize those characters which were somehow standard,
it was probably incorrect, the use of standard-char-p being in the same
space (in my mind) as evenp rather than integerp.
(This isn't a really good reason. I'll work on it.)
The reason for avoiding string-char is that it is too implementation
dependent whether a given actual character is in the class. (I'm less
convinced about this one than about the others.)
About FUNCTION: I agree that it is important to clean up the FUNCTION
class in Common Lisp. However, doing so implies more global changes than
are in the scope of the Object proposal; for example, it means requiring
that class FUNCTION be disjoint from other classes (including ARRAY,
LIST, and SYMBOL), and that FUNCTIONP be changed incompatibly.
This is thus a strategic issue: is the object proposal strong enough to
carry this cleanup of CL along with it, or should it be separated? (Or,
perhaps, the wording should be something like: when CL-cleanup votes to
clean up FUNCTION so that it is well specified, the FUNCTION class will
be part of the required hierarchy.)
I'm typing this in with no text editor so forgive my spelling,
organization.
Larry
∂22-Jan-87 0810 skeene@STONY-BROOK.SCRC.Symbolics.COM Inheritance of Methods
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 22 Jan 87 08:10:38 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 49103; Thu 22-Jan-87 11:11:50 EST
Date: Thu, 22 Jan 87 11:09 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Inheritance of Methods
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 21 Jan 87 23:10 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870122110907.4.SKEENE@JUNCO.SCRC.Symbolics.COM>
Date: 21 Jan 87 2010 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
There is now a section in concepts about inheritance of methods. The
description of this inheritance makes most sense for ``classical''
methods; some would argue that those are the only methods for which this
description makes sense. CONCEPTS now does not contain the phrase ``classical
method,'' and this description does not jive with the section ``Method
Selection and Combination.'' Though this might have been a useful way to
conceptualize methods in the old days, I think it is outmoded, and we
plan to delete the subsection of ``Inheritance'' called ``Inheritance of
Methods.''
-rpg-
Note that this section does not contain the phrase "classical method"
either.
The "Inheritance" chapter mostly talks about the inheritance of slots
and DEFCLASS options. But you have to talk about methods here, to some
degree. It would be misleading to say "The :accessor slot-option is
not inherited". That statement alone implies that if a superclass
gives the :accessor option, it has no effect on the subclass. But in
fact, that method is applicable for the subclass. It's important to
state that explicitly.
Also, it's important to mention that a class can have an applicable
method for accessing a slot, but if the class used :allocation :none for
that slot, using the method will result in an error.
The section also notes that the inheritance of methods works the same
way, regardless of whether the method was defined by DEFMETHOD or by one
of the DEFCLASS options.
I would suggest that we rewrite that short "Inheritance of Methods"
section if you want, but not remove it. One suggestions is to rename
it "Inheritance of Accessor Methods" and discuss it from that
perspective.
∂22-Jan-87 1140 Masinter.pa@Xerox.COM [Masinter.pa: Handling Common Lisp built in types]
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Jan 87 11:40:19 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 22 JAN 87 11:13:43 PST
Date: 22 Jan 87 11:14 PST
From: Masinter.pa@Xerox.COM
Subject: [Masinter.pa: Handling Common Lisp built in types]
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870122-111343-1424@Xerox>
I found the old mail, but it isn't as relevant as I thought. Just "for
the record" ....
I thought it was interesting to see what was "wrong" here.
----- Begin Forwarded Messages -----
Date: 18 Jul 85 07:43 PDT
From: Masinter.pa
Subject: Handling Common Lisp built in types
I think that we can regularize the handling of Common Lisp standard type
specifiers by categorizing them. I've been working on this for a while,
but still don't have it 100% right; but what do you think about the
general direction?
- - - abstract - - - - - - -
Abstract classes have no immediate instances, but are umbrellas for
various implementation-specific types. An :include of these types
inherits no structure or accessor functions.
atom, common, float, integer, t
array
vector
string
bit-vector
(array * (* * ...)) for between 0 and array-rank-limit *.
[Being able to :include these has implications for implementation of
vectorp, atom, etc.]
- - - virtual-structure - - - - - -
Some should be treated "as if" they had structure. An :include of these
inherits the slots as noted, and the corresponding accessor functions.
(Note that this may require special implementation, eg., if cons cells
are cdr-coded, but structures that :include them are not.)
Implementations may have other components, but the ones specified are
the only ones inherited.
cons (car cdr)
complex (realpart imagpart)
ratio (numerator denominator)
character (code bits font)
Except for conses and symbols, the slots are read-only.
Note: I'm reluctant to add
symbol (plist package name)
to this list.
- - - - - implementation - - - - - - -
Some are implementation-specific classes, with no visible internal
structure. One cannot :include these, although they can be used in type
specifiers.
bignum, fixnum, double-float, short-float, single-float
(vector type *), (simple-vector type (n))
(array type [*|(*+)]), (simple-array type (n)),
when "type" is "OK" (implementation or abstract or immutable-predicate).
Note that (array t (3 3)) is mutable, since you can displace an array.
{Do I understand this?}
(All vector and array constructed types excluding the ones allowed above
as "abstract". Note that we've made a distinction between "string" and
"(vector string-char)", requiring only that (vector string-char) be a
subtype of "string".)
- - - - - should-be-implementation - - - - -
Some should have been specified as having distinct data types, but
weren't. We could propose changing the Common Lisp spec to make it so,
but it would probably cause some trouble.
stream, package, readtable, hash-table, pathname, random-state
(It would actually be reasonable to make these abstract types. The
problem is that their place in the class hierarchy is ambiguous. It
would be better if we could specify that those types are also disjoint
with number, array, symbol, list. They then could be "abstract with
unspecified implementation", i.e., one could :include them, but would
inherit no structure even though any implementation would have
structure.)
- - - - - - - immutable-predicate - - - - - - - -
These are predicates which don't rely on mutable properties, but are
still not usually thought of in the class heirarchy:
bit, (integer low high)
(mod n), (signed-byte s) (unsigned-byte s) (rational low high) (*float
low high)
(and type1 type2 ...), (or type1 type2 ...), (not type1)
(when the subtypes are OK, of course)
- - - - - - - - mutable-predicate - - - - -
These can't be :included, and allowing them in discrimiantors leads to
problems too:
(*string size) (since you can change the size of a string)
keyword (since you can change the package of a symbol)
- - - - - - - oddities - - - - - -
Now, here come the ones left over:
compiled-function I'm reluctant to put this in with the "should be
implementation", but its out of place here.
function "may be used only for declaration and not for discrimination"
values "this type specifier is extremely restricted"
keyword (mutable, since you can change the package)
- - - - - - - - - - - -
Need a section "include: of classes with different metaclass". If you
include a class which has a different metaclass, the implementation of
the subclass may be completely different than the implementation of the
parent. In that case, the structure of slots isn't shared, and it may be
necessary to "copy down" any methods which refer to the parents
implementation!
- - - - - - - - - - - - - - -
----- End Forwarded Messages -----
∂22-Jan-87 1140 Masinter.pa@Xerox.COM Re: Inheritance of Methods
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Jan 87 11:40:07 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 22 JAN 87 10:59:00 PST
Date: 22 Jan 87 10:59 PST
From: Masinter.pa@Xerox.COM
Subject: Re: Inheritance of Methods
In-reply-to: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 22 Jan 87 11:09 EST
To: skeene@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870122-105900-1394@Xerox>
What gets inherited is more than accessors and less than methods, that
is, a subclass inherits the accessors, since, in some sense, the
accessors "belong" to the class. We are reluctant to say that subclasses
inherit "methods" because a multi-method may not "belong" to any one
class, and the analogy of inheritance implies the analogy of possesion.
What is important is that behavior, reflected in the availability of
accessors and the participation in method lookup, is inherited. What do
you think of "Inheritance of Behavior" for a section title?
∂22-Jan-87 1527 Bobrow.pa@Xerox.COM Re: Inheritance of Methods
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Jan 87 15:19:29 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 22 JAN 87 14:38:44 PST
Date: 22 Jan 87 14:41 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Inheritance of Methods
In-reply-to: Masinter.pa's message of 22 Jan 87 10:59 PST
To: Masinter.pa@Xerox.COM
cc: skeene@STONY-BROOK.SCRC.Symbolics.COM,
common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870122-143844-1217@Xerox>
We can say that a subclass inherits methods in the sense that any method
applicable to an instance of a class is also applicable to instances of
any subclass (all other arguments to the method being the same). For
methods that have only one specialized argument, for example the
accessors of a class, we say that subclasses inherit the use of those
methods from the super class.
danny
∂22-Jan-87 1527 Bobrow.pa@Xerox.COM Re: standard-type-classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Jan 87 15:19:49 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 22 JAN 87 15:08:25 PST
Date: 22 Jan 87 15:10 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: standard-type-classes
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 21 Jan 87
14:21 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870122-150825-1274@Xerox>
I think that the minimum standard for having a class is that
a) all instances of the class (or any subclass) can be identified as
being of that type. FUNCTION has a problem in that respect wrt lists.
b) all instances have to support a well defined ordering on any two
classes of which it is a subtype. ATOM cannot be a class i.e. which is
more specific a STREAM or ATOM (unless of course we install ATOM above
all user defined types etc.).
c) The class of any instance should be quickly determinable. Thus
standard-char might be a case which is outlawed since it is a char that
is member of a set. Probably bit (represented by an integer that is
either 1 or 0) also falls in this category.
Question. Should the same object have the same class (with the same
name) in all standard Common Lisp systems? What do we do about the
float set which has several different classes that may be collapsed.
This seems like a reason to omit (some) implementation dependent
classes.
NIL seems like a good name for the bottom of the class lattice, but if
CLASS-NAME can return NIL for unnamed classes, then NIL isn't such a
good name (too bad though). How about BOTTOM, or NOT-T, or EMPTY?
danny
∂22-Jan-87 1527 Bobrow.pa@Xerox.COM Re: change-class and class redefinition
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Jan 87 15:19:35 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 22 JAN 87 14:52:37 PST
Date: 22 Jan 87 14:54 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: change-class and class redefinition
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 22 Jan 87 00:57 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870122-145237-1241@Xerox>
I like the name class-changed. I also agree with DLW
that we should invent a term for generic-functions which you
are not supposed to call yourself. We will need this term in
the meta-object protocol chapter.
As an initial proposal, we could have "callable functions",
"specializable functions", and "functions that are both callable
and specializable". If they aren't specializable it's none of your
business whether or not they are generic, which is why I said
"functions" instead of "generic functions." Specializable means you
can define methods for them. I don't claim this is the best
terminology in the world!
I agree we need a term. Ones I like slightly better are "external" and
"internal" instead of callable/not callable since clearly someone calls
these functions someplace. It is just whether they are internal to the
implementation or not.
We already have the notion of specializable which means that methods may
be defined for a function that otherwise has none. But is this a case
in which what is intended by non-speicalizable does not imply that there
are no methods -- only that "user" whoever that is, should not add any
more. Under what circumstances does this make sense. Why should
functions ever be unspecializable. Only for implementation reasons I
feel (where assumptions have been bound into the code that is compiled).
If we can't finish change-class until we finish initialization
I will go back to working on initialization. I've been working on
that, in between interruptions, but don't have anything to report
yet.
I think initialization is more important (and I feel that we are
sufficiently close on change-class) that I would want to understand the
two together. I feel it would be worth more to see your ideas on
initialization sooner.
The rule is that newly created slots are initialized to the
value of their :initform. I'm assuming that the :initforms for
different slots are independent of each other and that the language
makes no commitment about the order in which :initforms will be
evaluated; are you assuming something different from that?
I agree with this. It is the assumption underlying the rule we proposed
for initialization that all initforms are run before further
initialization takes place.
... A slot is a conceptual entity, not a word of computer storage
at a particular address. No slot contents are being copied or
changed...
I like this model.
danny
ps Dave,
Did you see (and have a quick reaction) to the alternative
define-method-combination.
danny
∂22-Jan-87 1527 Bobrow.pa@Xerox.COM [Gregor Kiczales <Gregor.pa>: Re: STANDARD-TYPE-CLASS]
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Jan 87 15:20:02 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 22 JAN 87 15:16:01 PST
Date: 22 Jan 87 15:18 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: [Gregor Kiczales <Gregor.pa>: Re: STANDARD-TYPE-CLASS]
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870105-135407-3657@Xerox>
*** There were no comments on the following proposal from Gregor.
I think it is correct. Do we have a consensus on this? The most
controversial is the mixin stuff. Please respond right away with at
least one of
YES
NO - and here's what I think
no, and I'll get back to this later.
I am writing on the meta-object protocol and need to know.
****
The concept of built-in-class and standard-type-class as
defined by Dick are important and make sense. I think these should be
mixin's though since there are several possible reasonable combinations.
Something like the following seems right:
(defclass class () ()) ;the top
(defclass built-in-class-mixin (class) ()) ;microcode knows about
these
(defclass standard-type-class-mixin (class) ()) ;Steele knows about
these
(defclass standard-class (class) ()) ;defclass makes these
;;;
;;; Important combinations of the above:
;;;
(defclass standard-extensible-class (class standard-type-class-mixin)
())
(defclass standard-built-in-class (built-in-class-mixin
standard-type-class-mixin)
())
The following are values that MANY, but not all implementations would
return.
(class-of (class-named 'pathname)) ==> standard-extensible-class
(class-of (class-named 'cons)) ==> standard-built-in-class
(class-of (class-named 'stream)) ==> standard-class-mixin
These say that:
PATHNAME is a standard class defined by Steele, in addition, it can be
specified as a direct-superclass in a defclass form.
FIXNUM is a standard class defined by Steele. In addition, it is
represented "fundamentally" by this Lisp.
STREAM is a standard class defined by Steele. It is not represented
fundamentally by this Lisp, but it may not be included as a direct
superclass in a defclass form.
∂22-Jan-87 1556 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: standard-type-classes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 22 Jan 87 15:51:14 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 49659; Thu 22-Jan-87 18:51:52 EST
Date: Thu, 22 Jan 87 18:49 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: standard-type-classes
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870122-150825-1274@Xerox>
Message-ID: <870122184913.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 22 Jan 87 15:10 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
NIL seems like a good name for the bottom of the class lattice, but if
CLASS-NAME can return NIL for unnamed classes, then NIL isn't such a
good name (too bad though). How about BOTTOM, or NOT-T, or EMPTY?
Unless Common Lisp is going to change the name of the type specifier for
the bottom of its type (not-really-a-)lattice, I think it's much better
to change what CLASS-NAME returns for unnamed classes than to change the
name of the bottom class. If we need a bottom class, I think it needs
to be named NIL, because that is less confusing to a Common Lisp
programmer than any other name. I don't have a strong opinion yet on
whether or not we need a bottom class.
The draft specification as it stands contains neither CLASS-NAME nor
anonymous classes. Can we assume that someone is going to get their
act together and propose those at some point?
∂22-Jan-87 1603 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Inheritance of Methods
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 22 Jan 87 16:02:53 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 49678; Thu 22-Jan-87 19:02:13 EST
Date: Thu, 22 Jan 87 18:59 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Inheritance of Methods
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870122-143844-1217@Xerox>
Message-ID: <870122185939.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 22 Jan 87 14:41 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
We can say that a subclass inherits methods in the sense that any method
applicable to an instance of a class is also applicable to instances of
any subclass (all other arguments to the method being the same). For
methods that have only one specialized argument, for example the
accessors of a class, we say that subclasses inherit the use of those
methods from the super class.
I agree with this.
∂22-Jan-87 1603 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: change-class and class redefinition
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 22 Jan 87 16:02:16 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 49676; Thu 22-Jan-87 19:00:55 EST
Date: Thu, 22 Jan 87 18:58 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: change-class and class redefinition
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870122-145237-1241@Xerox>
Message-ID: <870122185820.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 22 Jan 87 14:54 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
I like the name class-changed. I also agree with DLW
that we should invent a term for generic-functions which you
are not supposed to call yourself. We will need this term in
the meta-object protocol chapter.
As an initial proposal, we could have "callable functions",
"specializable functions", and "functions that are both callable
and specializable". If they aren't specializable it's none of your
business whether or not they are generic, which is why I said
"functions" instead of "generic functions." Specializable means you
can define methods for them. I don't claim this is the best
terminology in the world!
I agree we need a term. Ones I like slightly better are "external" and
"internal" instead of callable/not callable since clearly someone calls
these functions someplace. It is just whether they are internal to the
implementation or not.
The reason I don't like "external" and "internal" is that these seem to
refer to the visibility of the name. An "internal" function that is
"specializable" by someone on the outside seems like a contradiction to
me. In other words, nothing obviously says that "external" and "internal"
refer to the calling side rather than the specializing side.
We already have the notion of specializable which means that methods may
be defined for a function that otherwise has none. But is this a case
in which what is intended by non-speicalizable does not imply that there
are no methods -- only that "user" whoever that is, should not add any
more.
Right.
Under what circumstances does this make sense. Why should
functions ever be unspecializable. Only for implementation reasons I
feel (where assumptions have been bound into the code that is compiled).
Then "specializable" means "this standard says you are supposed to
specialize this function as part of your normal programming", which is not
the same as the negation of "it is impossible to specialize this function."
I can see this is going to be hard to explain in a document, because there
are all these subtle distinctions.
To take examples from the current draft proposal, print-object is
specializable and not callable, while make-method is callable, not
specializable, and not generic, and get-method is callable, generic,
and not specializable at the outer layer of the standard, but
may be specializable (for some reason that isn't obvious to me)
at the meta-object layer of the standard. I don't know whether these
examples make it clearer or more obscure!
ps Dave,
Did you see (and have a quick reaction) to the alternative
define-method-combination.
I gave it a quick read but I'm not working on method combination this
month. It's too easy to use up all the time polishing the last details
of one issue to the total neglect of other equally important issues.
∂22-Jan-87 1610 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Inheritance of Methods
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 22 Jan 87 16:09:42 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 49698; Thu 22-Jan-87 19:10:30 EST
Date: Thu, 22 Jan 87 19:07 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Inheritance of Methods
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870122-105900-1394@Xerox>
Message-ID: <870122190755.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 22 Jan 87 10:59 PST
From: Masinter.pa@Xerox.COM
What gets inherited is more than accessors and less than methods, that
is, a subclass inherits the accessors, since, in some sense, the
accessors "belong" to the class. We are reluctant to say that subclasses
inherit "methods" because a multi-method may not "belong" to any one
class, and the analogy of inheritance implies the analogy of possesion.
I don't think that this slight flaw in the analogy is good grounds for
abandoning it, since it's such a powerful analogy. Multi-methods are inherited
from the several classes they belong to, by all of the subclasses of each of
those classes. I don't think this is stretching the analogy out of shape.
What is important is that behavior, reflected in the availability of
accessors and the participation in method lookup, is inherited. What do
you think of "Inheritance of Behavior" for a section title?
The document is already too vague. I don't think we should be adding more
vague words like "behavior" if we can help it. Everyone knows it is really
methods we are talking about, so we should say what we mean.
∂22-Jan-87 1642 Masinter.pa@Xerox.COM Re: Inheritance of Methods
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Jan 87 16:42:36 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 22 JAN 87 16:39:48 PST
Date: 22 Jan 87 16:40 PST
From: Masinter.pa@Xerox.COM
Subject: Re: Inheritance of Methods
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 22 Jan 87 19:07 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870122-163948-1501@Xerox>
I don't feel very strongly about the wording, and was just wanting to
offer some alternatives. Here's another alternative which is more
precise than "inheritance of behavior":
"Inheritance of method applicability"
That is, what subclasses inherit from their superclasses is the
applicability of methods to instances of them. In some cases, the class
of more than one argument comes into play, but the share of
responsibility for determining applicability is inherited.
Larry
(I started to explain how you could call the ownership of multi-methods
a partnership where the left-most class was the senior partner, but
that's certainly going to far down metaphor road. ouch -- lm :-)
∂22-Jan-87 1654 Bobrow.pa@Xerox.COM Re: standard-type-classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Jan 87 16:53:59 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 22 JAN 87 16:48:22 PST
Date: 22 Jan 87 16:50 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: standard-type-classes
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 22 Jan 87 18:49 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870122-164822-1526@Xerox>
The draft specification as it stands contains neither
CLASS-NAME nor anonymous classes. Can we assume that someone is
going to get their act together and propose those at some point?
The document should say something like:
Classes are first class objects. Unnamed classes can exist, created by,
for example, by
(MAKE-INSTANCE class direct-supers ...)
The user interface suports the notion of class-names to allow defclass
definitions to use names. The function interface to those classes
defined by DEFCLASS consists of:
(CLASS-NAMED <symbol> &optional (no-error ())
which returns the class currently having the name <symbol> or signals an
error if there is no such class if no-error is NIL. If no-error is
non-NIL, then CLASS-NAMED returns NIL if there is no such class.
(CLASS-NAME class &optional (unnamed-class-response 'NO-NAME))
This function returns the name originally provided by defclass if this
class still has that name, the value of unnamed-class-response if the
class has none. It is a hint in that it is NOT guaranteeed that
(CLASS-NAMED (CLASS-NAME class)) = class
The "natural" value of unnamed-class-response is () but this conflicts
with our desire to have a class named NIL.
danny
∂22-Jan-87 1700 Bobrow.pa@Xerox.COM Re: change-class and class redefinition
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Jan 87 16:59:54 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 22 JAN 87 16:59:18 PST
Date: 22 Jan 87 17:00 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: change-class and class redefinition
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 22 Jan 87 18:58 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870122-165918-1546@Xerox>
Then "specializable" means "this standard says you are supposed
to specialize this function as part of your normal programming",
which is not the same as the negation of "it is impossible to
specialize this function."
How about the term "tailorable function" for the sense of user is
expected to be able to tailor the system by providing a special method?
print-object
this one is callable. I agree with the rest of your examples, reprinted
here to try out the word tailorable.
make-method is callable, not tailorable, and not generic,
and get-method is callable, generic, and not tailorable at the
outer layer of the standard,
Dave, Did you see (and have a quick reaction) to the
alternative define-method-combination.
I gave it a quick read but I'm not working on method
combination this month. It's too easy to use up all the time
polishing the last details of one issue to the total neglect of
other equally important issues.
I wanted the bit of: how much would you object if this were put in
instead of the writeup you worked on? (It is a start) If you object too
much, and if we are not going to argue it out before the draft goes out,
then we should put in both choices.
danny
∂22-Jan-87 1701 RPG Inheritance of Methods
To: Common-lisp-object-system@SAIL.STANFORD.EDU
I agree with the following statement:
a subclass inherits methods in the sense that any method
applicable to an instance of a class is also applicable to instances of
any subclass (all other arguments to the method being the same). For
methods that have only one specialized argument, for example the
accessors of a class, we say that subclasses inherit the use of those
methods from the super class.
I do not agree that we should say that. I think it is forcing an
inappropriate metaphor too far.
On a related topic. Suppose C1 is a class with a slot named FOO and an
accessor method, C2 is a subclass with FOO subtracted out (the :allocation
is :none for that slot), and suppose that C3 is a subclass of C2 without
an accessor method.
Does the accessor method for FOO work on instances of C2? Of C3? Are
errors signalled?
-rpg-
∂22-Jan-87 2201 Masinter.pa@Xerox.COM Re: standard-type-classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Jan 87 22:01:31 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 22 JAN 87 22:01:55 PST
Date: 22 Jan 87 22:03 PST
From: Masinter.pa@Xerox.COM
Subject: Re: standard-type-classes
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 22 Jan 87 15:10 PST
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870122-220155-1729@Xerox>
"Question. Should the same object have the same class (with the same
name) in all standard Common Lisp systems? What do we do about the
float set which has several different classes that may be collapsed.
This seems like a reason to omit (some) implementation dependent
classes."
There are a number of examples where it seems clear that we want to make
no such requirement. For example, we don't want to require that
implementations *not* use the class system to implement stream classes,
e.g. (class-of (make-two-way-stream a b)) should not be required to be
the class STREAM but merely STREAM or some subclass of STREAM. I think
the floating point classes are in the same category, i.e., they are
"implementation-dependent classes" and code that discriminates on them
is allowed and implementation-dependent.
∂23-Jan-87 1123 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: standard-type-classes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Jan 87 11:23:10 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 50242; Fri 23-Jan-87 14:24:24 EST
Date: Fri, 23 Jan 87 14:21 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: standard-type-classes
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870122-220155-1729@Xerox>
Message-ID: <870123142149.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 22 Jan 87 22:03 PST
From: Masinter.pa@Xerox.COM
"Question. Should the same object have the same class (with the same
name) in all standard Common Lisp systems? What do we do about the
float set which has several different classes that may be collapsed.
This seems like a reason to omit (some) implementation dependent
classes."
There are a number of examples where it seems clear that we want to make
no such requirement. For example, we don't want to require that
implementations *not* use the class system to implement stream classes,
e.g. (class-of (make-two-way-stream a b)) should not be required to be
the class STREAM but merely STREAM or some subclass of STREAM. I think
the floating point classes are in the same category, i.e., they are
"implementation-dependent classes" and code that discriminates on them
is allowed and implementation-dependent.
I agree. Actually I'd like to strengthen it: to me, class-of is like type-of
and shouldn't be guaranteed portable. Specifically, when the standard says
an object is "of class X", that should -always- mean that class-of the object
is allowed to be a subclass of X.
It's worth pointing out again that the distinction between SINGLE-FLOAT
and DOUBLE-FLOAT is qualititatively different from the distinction between
FIXNUM and BIGNUM. The float types have behavioral differences and
implementations aren't allowed to convert one into the other, with
two exceptions: the clearly defined rules of floating point contagion;
and an implementation is allowed to collapse these into a single type.
FIXNUM and BIGNUM on the other hand are purely implementation types and
behave identically (except for speed).
∂23-Jan-87 1125 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Inheritance of Methods
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Jan 87 11:25:08 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 50244; Fri 23-Jan-87 14:26:04 EST
Date: Fri, 23 Jan 87 14:23 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Inheritance of Methods
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870122-163948-1501@Xerox>
Message-ID: <870123142329.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 22 Jan 87 16:40 PST
From: Masinter.pa@Xerox.COM
Here's another alternative which is more
precise than "inheritance of behavior":
"Inheritance of method applicability"
That is, what subclasses inherit from their superclasses is the
applicability of methods to instances of them. In some cases, the class
of more than one argument comes into play, but the share of
responsibility for determining applicability is inherited.
That's good.
∂23-Jan-87 1131 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: change-class and class redefinition
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Jan 87 11:31:26 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 50251; Fri 23-Jan-87 14:28:15 EST
Date: Fri, 23 Jan 87 14:25 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: change-class and class redefinition
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870122-165918-1546@Xerox>
Message-ID: <870123142540.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 22 Jan 87 17:00 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Then "specializable" means "this standard says you are supposed
to specialize this function as part of your normal programming",
which is not the same as the negation of "it is impossible to
specialize this function."
How about the term "tailorable function" for the sense of user is
expected to be able to tailor the system by providing a special method?
Tailorable or specializable are equally okay with me.
print-object
this one is callable.
The second sentence of its documentation says it isn't.
Dave, Did you see (and have a quick reaction) to the
alternative define-method-combination.
I gave it a quick read but I'm not working on method
combination this month. It's too easy to use up all the time
polishing the last details of one issue to the total neglect of
other equally important issues.
I wanted the bit of: how much would you object if this were put in
instead of the writeup you worked on?
Strenuously.
(It is a start) If you object too
much, and if we are not going to argue it out before the draft goes out,
then we should put in both choices.
Go ahead.
∂23-Jan-87 1141 Gregor.pa@Xerox.COM Re: standard-type-classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Jan 87 11:41:42 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 23 JAN 87 11:37:05 PST
Date: 23 Jan 87 11:37 PST
From: Gregor.pa@Xerox.COM
Subject: Re: standard-type-classes
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 23 Jan 87 14:21 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870123-113705-2375@Xerox>
Moon says:
I agree. Actually I'd like to strengthen it: to me, class-of is
like type-of
and shouldn't be guaranteed portable. Specifically, when the
standard says
an object is "of class X", that should -always- mean that class-of
the object
is allowed to be a subclass of X.
To be more specific, it isn't portable to say. (eq (class-of
*terminal-io*) 'stream), but it is portable to say (member (class-named
'stream) (class-class-precedence-list (class-of *terminal-io*))).
The distiniction I am drawing is that class-of, unlike type-of is
required to return the most specific class of which its argument is an
instance. But, when we specify classes, as when we specify types, we
mean that the object in question must be an instance of that class or
some subclass.
∂23-Jan-87 1142 Gregor.pa@Xerox.COM Re: change-class and class redefinition
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Jan 87 11:41:56 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 23 JAN 87 11:40:21 PST
Date: 23 Jan 87 11:40 PST
From: Gregor.pa@Xerox.COM
Subject: Re: change-class and class redefinition
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 22 Jan 87 00:57 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870123-114021-2379@Xerox>
Moon says:
However, this is missing the major point. I believe that "copying the
slots" is the wrong model of what is happening. A slot is a conceptual
entity, not a word of computer storage at a particular address. No slot
contents are being copied or changed. Some slots are being deleted,
some other slots are being newly created and therefore initialized, and
the rest of the slots remain unchanged. If a particular implementation
happens to work by moving the representation of a slot from location
1000 to location 1492, that's an implementation detail and not something
the programmer should see. At the level of abstraction that programmers
should deal with, a slot is a slot and nothing is being copied.
I like this argument, and am now happy with the change-class, class-changed part of this.
∂23-Jan-87 1204 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: change-class and class redefinition
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Jan 87 12:03:57 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 50251; Fri 23-Jan-87 14:28:15 EST
Date: Fri, 23 Jan 87 14:25 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: change-class and class redefinition
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870122-165918-1546@Xerox>
Message-ID: <870123142540.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 22 Jan 87 17:00 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Then "specializable" means "this standard says you are supposed
to specialize this function as part of your normal programming",
which is not the same as the negation of "it is impossible to
specialize this function."
How about the term "tailorable function" for the sense of user is
expected to be able to tailor the system by providing a special method?
Tailorable or specializable are equally okay with me.
print-object
this one is callable.
The second sentence of its documentation says it isn't.
Dave, Did you see (and have a quick reaction) to the
alternative define-method-combination.
I gave it a quick read but I'm not working on method
combination this month. It's too easy to use up all the time
polishing the last details of one issue to the total neglect of
other equally important issues.
I wanted the bit of: how much would you object if this were put in
instead of the writeup you worked on?
Strenuously.
(It is a start) If you object too
much, and if we are not going to argue it out before the draft goes out,
then we should put in both choices.
Go ahead.
∂23-Jan-87 1236 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: standard-type-classes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Jan 87 12:36:15 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 50329; Fri 23-Jan-87 15:09:56 EST
Date: Fri, 23 Jan 87 15:07 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: standard-type-classes
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870123-113705-2375@Xerox>
Message-ID: <870123150719.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 23 Jan 87 11:37 PST
From: Gregor.pa@Xerox.COM
The distinction I am drawing is that class-of, unlike type-of is
required to return the most specific class of which its argument is an
instance. But, when we specify classes, as when we specify types, we
mean that the object in question must be an instance of that class or
some subclass.
I agree. (My previous message saying class-of is like type-of might have
been taken as disagreement, but it wasn't.)
∂23-Jan-87 1241 RPG Strenuously
To: common-lisp-object-system@SAIL.STANFORD.EDU
Seeing how this how much Moon would object to Danny's alternative to
define-method-combination, we should possibly talk this one out face-to-face
in March. Which brings up the topic: Shall we meet before the X3J13 meeting
in Palo Alto to iron out some more details?
I'd like to say that the current writeup of method combination is vastly
better than anything I've seen so far, and that I don't quite understand
the ramifications of Danny's variant.
-rpg-
∂23-Jan-87 1350 Moon@STONY-BROOK.SCRC.Symbolics.COM Symbolics design review
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Jan 87 13:49:01 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 50466; Fri 23-Jan-87 16:49:43 EST
Date: Fri, 23 Jan 87 16:47 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Symbolics design review
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870123164705.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Symbolics is having an ongoing in-house design review of the proposed
standard. The reviewers understand that the proposal isn't finished yet,
but it seemed like a good idea to get some review before we mail it out to
the X3J13 folks. We had a meeting yesterday. Here are some highlights of
comments that people had. I've omitted editorial comments on the document
(although some were quite important) and also omitted comments that were
minor, that only indicated that things were hard to understand, or where I
wanted to think about it more before I could figure out how to summarize
what was said. I'll keep relaying additional comments as they crystallize.
The proposal in its current form is quite incomplete. Many functions that
one would expect to be there are missing, for instance there are functions
get class and method objects but little you can do with one once you've
gotten one. I explained that these were in the meta-object protocol that
wasn't written yet. It's really not that simple; there is a gray area
between full meta-objects (where the programmer is trying to use the
standard facilities as an assist in creating her own object-oriented
programming system) and simply wanting to access the standard meta-objects
without creating any new meta-object classes.
The lambda-list congruence rules need re-examination. Detailed comments
later.
Several people thought WITH-SLOTS was awfully verbose. No real conclusions
were drawn other than that Symbolics would continue to support the Flavors'
syntax of DEFMETHOD, with its useful implicit WITH-SLOTS.
Everyone found :allocation :none confusing and ill-motivated. A real
example of how to use it would help a lot. At first it seems to be
subtractive inheritance, a la Alan Snyder's Common Objects, but this
example shows that it doesn't do that:
(defclass c1 () (a :initform 2))
(defclass c2 (c1) ((a :allocation :none)))
(defclass c3 (c2) (a))
and the A slot of a C3 is initialized to 2. The group also wasn't happy
with the idea that c2 "breaks" c1. Maybe :allocation :none is really for
something else, such as "abstract" slots that show up in with-slots and
have access methods, but aren't explicitly stored? Anyway we'd like to see
some motivation and an example, or if there isn't any then we think it
should be flushed, because it is so confusing and hard to explain.
Many things are not explained very well and people couldn't understand
them from the document; they had to be explained verbally. I guess we
ought to put together a list of these.
ADD-METHOD, REMOVE-METHOD, GET-METHOD don't seem to work right; things
that should work signal an error (details later).
The Design Rationale section is out of date and extremely incomplete.
It's important to flesh this out.
That's it for today.
∂23-Jan-87 2139 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 23 Jan 87 21:38:58 PST
Received: from ti-csl by csnet-relay.csnet id ba04256; 24 Jan 87 0:26 EST
Received: from Jenner (jenner.ARPA) by tilde id AA23277; Fri, 23 Jan 87 15:17:06 cst
To: Bobrow.pa@XEROX.COM
Cc: common-lisp-object-system@SU-AI.ARPA
Date: 23-Jan-87 15:15:45
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Message-Id: <DUSSUD.2747423742@Jenner>
Subject: Re: New version of define-method-combination
The following is an alternate version of define-method-combination.
It has the following properties:
1) There is only one define-method-combination form. It allows easy
support of around methods, and supports error checking. Defining simple
combinations is easy and concise.
Sounds good to me.
2) There is no lambda-list. It also omits the keyword :order from the
method specifier. defgeneric-options is extended to store parameters
in the generic function. This can be used to support features like
reversed order for <and> combination if desired.
There is a problem in tying up the parameters of the method combination to the generic function.
If the user has to access those from the generic function, extensions where there
can be several method combinations defined for the same generic function will not work.
Parameters passed explicitly to the method combination function avoid this problem.
4) It uses the keyword :call-next-method instead of :around in
make-method-call. This eliminates confusion with respect to use of
this keyword with primary methods, and with respect to the new :around
keyword in method-combination options used to support around methods.
Thus
(make-method-call primary :around t)
becomes
(make-method-call primary :call-next-method t)
This renaming needs to be carried through to the functi
chapter.
I don't have any feeling for this one.
Text that looks similar to that in the concep chapter was in fact taken
from there, and no changes were made in most paragraphs.
I am recommending that we include this instead of the
current version in concep.
The rest of the message (TEX source) is painful to read.
*** Extension to defgeneric-options
defgeneric-options
{\bf :method-combination }
The list that is cdr of the option form is stored
in the generic-function object in the slot
{\it method-combination\/}.
Example:
(:method-combination and :most-specific-last)
stores {\it (and :most-specific-last)\/} in the slot
{\it method-combination\/}.
The body of compute-effective-method can get this information
from the generic-function using the slot-accessor.
***
*** Alternate version of define-method-combination***
\beginSection{Declarative Method Combination}
\beginsubSection{Defining Form for Method Combination}
The programmer can define new forms of method combination using the {\bf
define-method-combination} macro. This allows customization of step~3
of the method combination procedure. The body of {\bf
define-method-combination\/} used resembles {\bf defmacro\/} in that the
body is an expression that computes a Lisp form, usually using
backquote. Thus, an arbitrary combination of methods can be
constructed.
%The following syntax expressions need to be converted to TEX
(DEFINE-METHOD-COMBINATION name [macro]
({method-group-specifier}+ )
[({method-combination-option}*)]
{form}*)
{method-group-specifier}:= (variable { {qualifier-pattern}+ | predicate}
{keyword argument}*)
The method-group-specifier predicate is a good thing to have.
{method-combination-option} :=combination-keyword value
{\bf :around} {\it boolean\/}
If the argument is true (not {\bf nil}),
then the form returned by the body of define-method-combination
is augmented to support :around methods. See examples below.
This keyword option is a convenience and does not add any
expressive power. It is provided so that programmers are not
tempted to omit support for :around methods. Methods matching
(:around) are extracted first from the list of applicable
methods. If {\bf :around} is not specified, it defaults to
{\bf nil}. The argument {\it boolean\/} is not evaluated.
;The default method-combination, the hard way
(define-method-combination standard
((around (:around))
(before (:before))
(primary ())
(after (:after)))
(unless primary
(method-combination-error "A primary method is required."))
(make-method-call `(,@around
(multiple-value-prog2
,(make-method-call before)
,(make-method-call primary :call-next-method t)
,(make-method-call (reverse after))))
:call-next-method t))
;The default method-combination using keyword options
(define-method-combination standard
((before (:before))
(primary () :required t)
(after (:after)))
(:around t)
(multiple-value-prog2
,(make-method-call before)
,(make-method-call primary :call-next-method t)
,(make-method-call (reverse after))))
I am not sure that the :around keyword actually simplifies things. It hides the around
mechanism, but seeing the actual code helps people to get the right model in their minds.
Despite these points, we seem to be converging on this issue.
Patrick.
∂24-Jan-87 1528 RPG Alternatives
To: common-lisp-object-system@SAIL.STANFORD.EDU
We should avoid writing alternatives into the document at almost any cost.
The purpose of this subgroup is to present our best proposal with as few
choices left open as possible. If we leave alternatives in the document we
invite perpetual and irritating debate. I do not want to have two nearly
identical define-method-combination writeups. I do not want a precise CPL
computation section followed by a ``you can predict'' section.
If {we | this group | this committee | Danny, Gregor, Moon, and I} {cannot
| will not} {make | come to | agree upon} {a reasonable | an acceptable}
{decision | consensus}, how can the committee as a whole?
-rpg-
∂25-Jan-87 1530 Moon@STONY-BROOK.SCRC.Symbolics.COM Comments on Concepts chapter 1/23/87
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 25 Jan 87 15:30:14 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 51316; Sun 25-Jan-87 18:27:30 EST
Date: Sun, 25 Jan 87 18:27 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Comments on Concepts chapter 1/23/87
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870125182731.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Here are my comments on the latest Concepts chapter, except for minor
editorial points. Indented text is from the document source. Page
numbers are from the Jan 15 version, but should be close. I've omitted
comments that have already been resolved in the Jan 23 source; I haven't
seen a Jan 23 hardcopy yet, so I might later have more comments on
things that were added in that version.
p1-3:
The naming conventions for generic functions are
precisely the same as those for ordinary Common Lisp functions.
Huh? I can't figure out what, if anything, this is supposed to mean.
A method---also
called a {\bit method object}---is a function that can be used in any
of the ways that ordinary functions can be used in Common Lisp.
Is this intended to imply that FUNCALL of a method object is allowed? I
strongly disagree with that. We agreed that FUNCALL of a
generic-function object is allowed, but that is an entirely different
story. I strongly believe that the standard should specify that methods
can only be called by the internal mechanisms of the implementation of
generic functions, not directly by the user.
A method object contains a method function and a set of {\bit parameter
specializers\/} that specify when the given method is applicable.
Qualifiers, too.
p.1-5:
Like other objects, all classes are themselves instances of classes....
This paragraph is too early. Metaclasses should not be mentioned until the
basics of classes have been discussed. A good place would be at the end of
this subsection, right before \beginsubSection{Defining Classes}.
We will say that a class,
$C\sub{1}$, is a {\bit superclass\/} of a class, $C\sub{n}$, if there
exists series of classes, $C\sub{2},\ldots,C\sub{n-1}$ such that
$C\sub{i+1}$ is a direct superclass of $C\sub{i}$, for $1 \leq i<n$.
"series" -> "a series"
The last occurrence of "superclass" should be "subclass" (no wonder no
one could understand this paragraph!).
We refer to the set of classes consisting of some given
class $C$ along with all of its superclasses as ``the classes at or
above $C$.''
Ugh! Can't we find a more concise term for this? At least in the latest
version (unlike Jan 15) the term seems to be used consistently.
Classes are organized into a {\bit lattice}, which gives them a....
This whole paragraph doesn't make complete sense, because there is not
-one- local precedence order; there is a separate local precedence order
for each component class, and all of them are taken into account.
The discussion would be clearer if the local precedence order of a class
was defined to be the list formed by consing the name of the class onto
the front of its list of direct superclasses. This local precedence
order, as a total order, expresses all of the constraints. The
computation of the overall class precedence list can be described
entirely in terms of the local precedence lists, without the confusing
extra complexity of the lattice. The lattice concept could be dumped
entirely, or could be retained for explanatory purposes in other parts
of the document, but when describing the class precedence list it just
gets in the way. Thus I would rewrite these two paragraphs as follows:
When a class is defined, the order in which its direct superclasses
are mentioned in the defining form is important. Each class has a
{\bit local precedence order\/}, which is a list consisting of the
class, followed by its direct superclasses in the order mentioned
in the defining form, followed by the class {\bf t}.
Each class has a {\bit class precedence list}, which is a total order
on the set of classes at or above a given class. The total order is
expressed as a list ordered from most specific to least specific. The
class precedence list is used in several ways. In general, more
specific classes override features inherited from less specific
classes. The method selection and combination process uses the class
precedence list to order methods from most specific to least specific.
When one class has several superclasses, a more specific class can
override some of the options declared in the {\bf defclass} form of a
less specific class.
A class precedence list is always consistent with the local precedence
order of each class in the list. The classes in each local precedence
order appear within the class precedence list in the same order. If
the local precedence orders are inconsistent with each other, no class
precedence list can be constructed, and an error will be signalled.
The class precedence list and its computation will be discussed at
length below.
p.1-7: The detailed description of the syntax of defclass ("first element",
"second element") might better be left to Chapter 2. Too much information
from preceding and following sections is duplicated here, and often what
is said here is incomplete or incorrect.
If a local description of a slot is provided, it completely overrides any
description of that slot inherited from a superclass.
This is not true.
The fourth element is the set of class options, which....
The class options are the rest of the form, not an element of the form.
p.1-8: The concept of slot is never really explained. "The Structure of
Instances" would be a good section in which to explain it. The explanation
should start with the concept that there is a list of names (symbols, with
the same restrictions as variable names in LET) not containing any
duplicates, and with each name can be associated a value and some slot
options. The scope of the association depends on the :allocation.
Creating a type by means of {\bf defstruct} creates a class in this
lattice. Such a class is an instance of {\bf structure-class} and a
direct subclass of the class that corresponds to the type given as
its {\bf :includes} argument. If no classes are included, the new class
is a direct subclass of the class {\bf t}.
I think the last sentence should be deleted, because I'm not sure it's
true and because I don't think it matters whether something is a direct
subclass of T. As far as I can tell that either has no effect, or makes
the class precedence list computation signal an error, depending on
whether T is in the middle or at the end of the list of direct
superclasses. Just qualify the second-to-last sentence with "if any."
p1-12 {Inheritance}:
In spite of several go-rounds, the slot inheritance discussion is
complicated and confusing. This may be partly a reflection of the
design, but lacking any ideas for improving the design right now, let me
suggest improving the discussion. I think a lot of the problem is the
confusing concept of slots provided by or belonging to a superclass;
there is no such thing: only instances have slots, what a superclass
provides is a slot-description, not a slot. Also I think the whole
superclass/subclass orientation of the presentation is more confusing
than helpful.
Instead, I would speak of slot descriptions provided by classes in the
class precedence list. Case 1 in the existing text is the case where
only one class provides a slot description, which is quite simple. The
existing explanation is almost okay.
The other case is where -more- -than- -one- class in the class
precedence list provides a slot description with a given name. There is
always only one slot created, and its characteristics involve some
combination of the several slot descriptions. The slot options provided
by the various slot descriptions combine as follows:
:allocation comes from the most specific slot description -- if it
doesn't specify :allocation explicitly, :allocation :instance by default.
:initform comes from the most specific slot description that specifies
:initform explicitly.
:type is the AND of all the :types. [At least, this seems to be the
only rule that makes it possible for the compiler to exploit the
:type information at all, other than requiring each slot-description
to specify exactly the same :type.]
:reader and :accessor create methods at defclass time, and these methods
are applicable, but the slot options themselves don't do anything at
class combination time.
This should be a lot simpler.
Somewhere (I have it written on the Inheritance page, but I think it
might belong with the not-yet-existent general discussion of slots) it
should be clarified that methods know only the slot names. (The above
isn't strictly true now that :type has been introduced. Methods know
the slot names -and- types, which is why types can only be restricted,
not expanded, by inheritance.) Thus a method expecting to access a
:allocation :class slot, applied to an instance of a subclass that
redefines the slot with that name to be a :allocation :instance slot,
will access the instance slot instead.
Question about :allocation :none. Does this mean that there is no slot
by this name, or that there is a slot but an error is signalled if you
access it? The difference would be in the set of lexically apparent
variables created by with-slots. I think the answer should be that there
is a slot.
p.1-24 {Determining the Class Precedence List} (moved to an earlier page
in the latest version of the document, which I think was an improvement):
When one class has several superclasses, a more specific
class can override....
This happens even with one superclass, so delete the "when" clause.
See my previous comment that the local precedence order concept provides
all of the constraints and the lattice concept is not needed. With that
simplification, I think this way of describing the class precedence
computation would be okay with me. My only other complaint is that the
original concept of local rules controlling what happens, so that the
programmer can understand things locally without having to take a global
view, has been buried under a flood of mathematics. The concept is
still there, but it takes a determined reader to find it. I think it
would be better to start this section with that concept, perhaps using
some text from the previous version of the section, and use that as
motivation for the mathematical discussion.
I found the description of preorder treewalk virtually incomprehensible.
I know what it's trying to say, and agree with that, but the way it is
said needs to be rewritten or clarified.
p.16 {Introduction to Generic Functions}:
Typically a generic function object is stored as the function definition
of the symbol that is the name of the generic function.
This sentence should be put in its own paragraph and augmented with a
clarification that this is the -only- association from the name to the
generic function. Both defgeneric-options and defmethod use
symbol-function of the name to find the generic-function. The next
paragraph only mentions defgeneric-options, but most of what it says
applies to defmethod, too. (And the -setf versions also, of course.
Their difference is that they use get-setf-generic-function in place
of symbol-function.)
SETF generic functions are never explained anywhere. Most Symbolics
design reviewers found them completely incomprehensible. A section
explaining them should be added between {Introduction to Generic Functions}
and {Introduction to Methods}. If no one can be found to write this,
put in a blank section as a placeholder.
p.1-17 {Introduction to Methods}:
Only required parameters can be specialized.
I would add "A future extension might allow optional and keyword
parameters to be specialized" so that people know where we are coming
from.
A parameter specializer
is a list, {\tt ({\it variable-name parameter-specializer\/})},
where {\it parameter-specializer\/} is one of:
This is using "parameter specializer" to mean two different things.
Someone changed the previous text "A specialized parameter specifier is
a list..." to this; the previous version was at least correct, although
awkward. "Parameter specifier" is a term defined in CLtL.
The separate bullets for "any class" and "standard type class" are
extremely confusing. The reader wonders why "standard type class" is
mentioned separately and whether "any class" somehow doesn't include it.
Note that a parameter specializer cannot be a type specifier list,
such as {\tt ({\bf vector single-float})}.
This seems to be the last residue of a discussion of the relationship
between parameter specializers and type-specifiers. I strongly believe
that the rest of that discussion should be restored. The point is that
parameter specializers are a subset of type-specifiers, and thus
discrimination can be understood in terms of typep, and more
importantly, we are extending the Common Lisp type system upward
compatibily, not creating yet another type system.
Also the requirement that Common Lisp be modified to include
(deftype quote (object) `(member ,object)) has been removed from
the document and needs to be restored.
p1-19 {Method Selection and Combination}:
The \numitem headings don't stand out adequately. Someone who knows TEX
should fix this section to use a more appropriate TEX feature.
At the end of step 2, or perhaps at the end of the section, add a remark
that two methods with identical specializers but different qualifiers
will not be ordered by this algorithm. Normally this is okay, because
the two methods will play different roles in the effective method
because they have different qualifiers, and no matter which order they
appear in, in the result of step 2, the effective method will be the
same. If the two methods play the same role, so that their order
matters, implementations are encouraged to signal an error (this would
happen as part of qualifier-pattern matching in
define-method-combination). I don't mind requiring instead of
encouraging signalling an error, but this verges on program development
tools so perhaps others would object. It is impossible for there to be
two methods for a single generic function with identical specializers
-and- identical qualifiers, because defining the second would replace
the first (see defmethod, add-method).
p1-27: {Short Form of Define-method-combination}:
I'm tempted to eliminate the operator as a positional argument and
replace it with a :operator keyword option. The operator is usually
the same symbol as the name.
p1-28 {Long Form of Define-method-combination}:
Could someone who knows TEX convert the syntax expression to TEX?
Thus a qualifier-pattern can be the empty list {\bf ()}
(which matches primary methods, which are always unqualified)
This is wrong. "Primary methods" and "unqualified methods" are two
separate concepts. For standard method combination they happen to be
equal sets of methods, but that's essentially a coincidence. The
correct parenthetical expression is "(which matches unqualified
methods)".
p1-34 Meta objects:
\CLOS\ provides several predefined meta-objects: {\bf generic-function}
(the default class of a generic function), {\bf method} (the default
class of a method), {\bf class} (the default class of a user-defined
class), and the standard method-combination type).
I thought method combination types were not objects in their own right,
but were just methods. I have no real objection to making them into
objects, although it doesn't seem like anything would be gained by
doing so.
I also thought we were going to change these names, but maybe that
discussion is still ongoing.
∂25-Jan-87 1652 RPG Moon's comments
To: common-lisp-object-system@SAIL.STANFORD.EDU
Moon writes:
``Huh? I can't figure out what, if anything, this is supposed to mean.''
This was about a terse comment acncerning naming generic functions. In a
previous draft there were several sentences talking about the names of
generic functions as if there were such things.
``The name of a generic function is in a certain package and can be...''
``Typically a generic-function object is stored as the function definition
of the symbol that is the name of the generic function...''
These two sentences gave the impression that generic functions are named
in a way that functions are not. The sentence Moon objects to,
``The naming conventions for generic functions are precisely the same as
those for ordinary Common Lisp functions,''
is an attempt to eliminate that impression.
The definition of superclass should really read:
We will say that a class
$C\sub{n}$ is a {\bit superclass\/} of a class $C\sub{1}$ if there
exists a series of classes $C\sub{2},\ldots,C\sub{n-1}$ such that
$C\sub{i+1}$ is a direct superclass of $C\sub{i}$, for $1 \leq i<n$.
De-TEXifying:
We will say that a class
Cn is a *superclass* of a class C1 if there
exists a series of classes C2,...,Cn-1 such that
Ci+1 is a direct superclass of Ci, for 1<=i<n.
Moon writes about ``classes at or above a given class'':
``Ugh! Can't we find a more concise term for this?''
It's not worse than ``less than or equal,'' which was the model for it.
I, apparently, was the only person to try to think of a name, so someone
else should propose one.
Moon writes:
``This whole paragraph doesn't make complete sense, because there is not
-one- local precedence order; there is a separate local precedence order
for each component class, and all of them are taken into account.''
And then he proposes an alternate explanation. I think that breaking things
down into a lattice with ordered direct superclasses makes understanding
easier than clumping things together. It also gives the readers something
to hang onto that they already understand - lattices. Also, we don't have
to think of a name for the class inheritance structure. The description of
the computation has been clarified somewhat over what Moon has seen.
Moon then comments on the ``flood of mathematics'' in the description of
the CPL computation. The description of the CPL computation is meant to be
precise. We are writing a specification, not a user's guide. Let the
companies write user's guides. My own canvassing of readers showed that
the explanation based on local rules - the explanation that was in
CONCEPTS earlier and which I replaced with the current explanation - was
not understandable by a range of people, including algorithms hackers.
The most experienced algorithms hackers were not entirely sure that the
rules provided a well-defined total ordering, nor did they completely
believe that the algorithm would run in reasonable time.
I will need major convincing that a second explanation is needed. Perhaps
we need to work on the current one to make it understandable to
casual readers, but that is a separate affair. I will take a try at
re-writing the computation description using the local precedence
order definition Moon suggested.
Moon writes:
``I found the description of preorder treewalk virtually incomprehensible.``
Gabriel collapses. I really, really find this hard to believe. Let's look
at it:
``A preorder treewalk is defined in terms of the order in which classes
are visited while performing a process called ``walking from a class.''
The following is a recursive definition of walking from a class. Let C be
a class and let C1...Cn be its direct superclasses in the local precedence
order. Nodes are visited unless they have already been visited. To walk
from C, first C is visited, then we walk from C1, then we walk from C2,
and so on until we finally walk from Cn.''
I can write the program to do this from this description. This description
is about as closely copied from Knuth as it can be, given that we don't have
trees and that the same classes can be encountered by different paths.
-rpg-
∂25-Jan-87 1840 Moon@RIVERSIDE.SCRC.Symbolics.COM Gabriel's comments
Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 25 Jan 87 18:39:25 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 95927; Sun 25-Jan-87 21:37:36 EST
Date: Sun, 25 Jan 87 21:37 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Gabriel's comments
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 25 Jan 87 19:52 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870125213743.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 25 Jan 87 1652 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Moon writes:
``Huh? I can't figure out what, if anything, this is supposed to mean.''
This was about a terse comment acncerning naming generic functions. In a
previous draft there were several sentences talking about the names of
generic functions as if there were such things.
``The name of a generic function is in a certain package and can be...''
``Typically a generic-function object is stored as the function definition
of the symbol that is the name of the generic function...''
These two sentences gave the impression that generic functions are named
in a way that functions are not. The sentence Moon objects to,
``The naming conventions for generic functions are precisely the same as
those for ordinary Common Lisp functions,''
is an attempt to eliminate that impression.
Elsewhere in my comments I suggested saying very explicitly that generic
functions are named in the same way as regular functions, and describing
quite explicitly the way that defmethod and defgeneric-options call
symbol-function, so this can be folded into that. We're agreeing with each
other, and we just need to wring out ambiguities of English.
The definition of superclass should really read....
Your revised definition is good.
Moon writes about ``classes at or above a given class'':
``Ugh! Can't we find a more concise term for this?''
It's not worse than ``less than or equal,'' which was the model for it.
I, apparently, was the only person to try to think of a name, so someone
else should propose one.
I've proposed one. Several times. Remember "component"?
Moon writes:
``This whole paragraph doesn't make complete sense, because there is not
-one- local precedence order; there is a separate local precedence order
for each component class, and all of them are taken into account.''
And then he proposes an alternate explanation. I think that breaking things
down into a lattice with ordered direct superclasses makes understanding
easier than clumping things together.
Either you didn't understand what I said or I didn't understand what you
just said. I don't see that any concepts that ought to be separate
would be clumped together. My suggestion would allow you to eliminate
the references to C-sub-l and speak only of C-sub-P (using the
terminology in the latest version of the file). It also would not be
necessary to speak of the second and third partial order any more. The
whole explanation would get simpler. You'd be describing the same
program behavior with half as many words and concepts, so it would be
correspondingly easier for the reader.
It also gives the readers something
to hang onto that they already understand - lattices.
I'm not sure that's a virtue, since the rules here are different from
the rules for lattices and intuition about lattices might be misleading.
However, the thought that giving readers a lattice to hang onto might
still be useful is why I suggested maybe using lattices as a heuristic.
Also, we don't have
to think of a name for the class inheritance structure. The description of
the computation has been clarified somewhat over what Moon has seen.
Actually I was reading your new version. That allowed me to omit a lot of
comments addressed to problems in the previous version that you had already
corrected.
Moon then comments on the ``flood of mathematics'' in the description of
the CPL computation. The description of the CPL computation is meant to be
precise. We are writing a specification, not a user's guide. Let the
companies write user's guides. My own canvassing of readers showed that
the explanation based on local rules - the explanation that was in
CONCEPTS earlier and which I replaced with the current explanation - was
not understandable by a range of people, including algorithms hackers.
The most experienced algorithms hackers were not entirely sure that the
rules provided a well-defined total ordering, nor did they completely
believe that the algorithm would run in reasonable time.
I think I was the first to say that the previous explanation was not good.
Your replacement explanation is definitely better. I am trying to improve
it further with my suggestions.
I will need major convincing that a second explanation is needed. Perhaps
we need to work on the current one to make it understandable to
casual readers, but that is a separate affair. I will take a try at
re-writing the computation description using the local precedence
order definition Moon suggested.
Please note that I did not suggest adding a second explanation. I
suggested eliminating unnecessary complexity from the current one (with
no thought of casual readers, incidentally), plus adding some motivation
(partly for casual readers, partly so the X3J13 committee will be able
to understand what we are presenting them with in a reasonable amount of
time). In making a proposal, I believe that motivation for why things
are proposed to be a certain way is nearly as important as a precise
description of the particular way they are proposed to be. This makes
it much easier to evaluate the proposal, and it makes implementors
likely to implement the proposal with fewer mistakes.
Moon writes:
``I found the description of preorder treewalk virtually incomprehensible.``
Gabriel collapses. I really, really find this hard to believe. Let's look
at it:
``A preorder treewalk is defined in terms of the order in which classes
are visited while performing a process called ``walking from a class.''
The following is a recursive definition of walking from a class. Let C be
a class and let C1...Cn be its direct superclasses in the local precedence
order. Nodes are visited unless they have already been visited. To walk
from C, first C is visited, then we walk from C1, then we walk from C2,
and so on until we finally walk from Cn.''
I can write the program to do this from this description.
So can I. I don't see what that has to do with it. It took me just as long
to understand the English as it would have taken to write and debug the program,
and I don't see why we can't do better than that. If we can't, let's put the
program in the document and take out the English.
This description
is about as closely copied from Knuth as it can be, given that we don't have
trees and that the same classes can be encountered by different paths.
∂25-Jan-87 2157 Moon@STONY-BROOK.SCRC.Symbolics.COM Class-precedence-list computation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 25 Jan 87 21:57:13 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 51424; Mon 26-Jan-87 00:55:43 EST
Date: Mon, 26 Jan 87 00:55 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Class-precedence-list computation
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870126005535.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Dick, your algorithm does not produce the same results as the Flavors
algorithm, assuming that I didn't make any mistakes in coding it
based on the description in the current document.
The topological sort is the same, but the resolution of cases where the
topological sort has several choices is not the same. The simplest test
case I could construct to demonstrate this is:
(DEFCLASS PTEST1 (PTEST2 PTEST3 PTEST5) ())
(DEFCLASS PTEST2 (PTEST5) ())
(DEFCLASS PTEST3 (PTEST4) ())
(DEFCLASS PTEST4 () ())
(DEFCLASS PTEST5 () ())
(PREORDER 'PTEST1) is (PTEST1 PTEST2 PTEST5 PTEST3 PTEST4)
Flavors order is (PTEST1 PTEST2 PTEST3 PTEST4 PTEST5 T)
Gabriel order is (PTEST1 PTEST2 PTEST3 PTEST5 PTEST4 T)
I couldn't find a test case with fewer than five classes.
I wrote a program to try both sets of rules on a bunch of Flavors-based
programs and show the difference not only in the class precedence list,
but in the inheritance of methods. I haven't fully evaluated the
results yet, but they seem to show that the Gabriel algorithm, although
it seems very straightforward, actually produces rather surprising
results. Here is an example that I boiled down from a real Flavors
example (the real example had a lot more classes, but the bulk of them
were irrelevant to the issue). I changed all the names to protect the
innocent:
(DEFCLASS PPTEST1 (PPTEST-MIXIN PPTEST2 PPTEST3) ())
(DEFCLASS PPTEST-MIXIN (PPTEST3) ())
(DEFCLASS PPTEST2 (PPTEST-INTERMEDIATE-1) ())
(DEFCLASS PPTEST3 (PPTEST-INTERMEDIATE-2) ())
(DEFCLASS PPTEST-INTERMEDIATE-1 (PPTEST-BASE) ())
(DEFCLASS PPTEST-INTERMEDIATE-2 (PPTEST-BASE) ())
(DEFCLASS PPTEST-BASE () ())
Flavors order:
PPTEST1, PPTEST-MIXIN, PPTEST2, PPTEST-INTERMEDIATE-1, PPTEST3,
PPTEST-INTERMEDIATE-2, PPTEST-BASE, T
Gabriel order:
PPTEST1, PPTEST-MIXIN, PPTEST2, PPTEST3,
PPTEST-INTERMEDIATE-2, PPTEST-INTERMEDIATE-1, PPTEST-BASE, T
Here the surprising thing is that PPTEST-INTERMEDIATE-1 is made less
specific than PPTEST-INTERMEDIATE-2. That's because PPTEST2 comes
-after- PPTEST3 in the preorder treewalk, even though PPTEST2 is
explicitly specified to come before PPTEST3 in the class precedence
list. PPTEST3 sneaks into the preorder treewalk early via PPTEST-MIXIN,
but cannot be earlier than PPTEST2 in the class precedence list.
The preorder is:
(PPTEST1 PPTEST-MIXIN PPTEST3 PPTEST-INTERMEDIATE-2
PPTEST-BASE PPTEST2 PPTEST-INTERMEDIATE-1)
I think this shows that the preorder treewalk is not a very good model
of the desired precedence order. It's intended as an approximation to
the Flavors rule of putting things in as they are encountered in the
treewalk (that damn rule for which we have yet to come up with a
coherent statement, except in Lisp code, that makes sense to anyone),
but it's an insufficient approximation.
It's true that the user did not explicitly declare that
PPTEST-INTERMEDIATE-1 is more specific than PPTEST-INTERMEDIATE-2, but
it's a surprise to find that the superclasses are in the reverse order
of the subclasses. For more discussion of that, see the message I sent
on 22 November.
I'm not sure yet where we should go from here. Flavors-based programs are
the only reservoir of real-world examples easily available to me. Someone
might want to argue that they are all garbage and we have no lessons to
learn from them, but I won't be convinced by anything less than another
body of real-world experience that produces opposite conclusions. Probably
the most productive thing for me to do next would be to think about a
coherent statement of that Flavors rule designed to fit into the framework
of Dick's explanation of class precedence computation, where the preorder
treewalk is now.
I haven't tried coding Danny's algorithm (proposed a month or two ago)
yet. I wonder if it does the same thing as either of these other
algorithms.
∂26-Jan-87 1413 Gregor.pa@Xerox.COM symbols are not generic functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Jan 87 14:13:36 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 26 JAN 87 14:13:51 PST
Date: 26 Jan 87 14:12 PST
From: Gregor.pa@Xerox.COM
Subject: symbols are not generic functions
To: Common-Lisp-Object-System@Sail.Stanford.edu
cc: Gregor.pa@Xerox.COM
Message-ID: <870126-141351-4399@Xerox>
symbols are not generic functions, they can only be used to name a
generic function. The primitive levels of the meta-interpreter deal
with generic-function objects. symbols as names of generic functions
are a convenience provided by defmethod, defmethod-setf
defgeneric-options etc.
Consequently, I would like to propose the following change.
I suggest that add-method, remove-method and get-method be changed to
require that their first argument be a generic-function object. Along
with this I would like to introduce a new function which will provide
the functionality I am proposing we remove in a more rational way.
ensure-generic-function (or some such name) takes a symbol, or a list
(SETF <symbol>) and makes sure there is a generic function of the
default kind (standard-generic-function) "there". For convenience,
ensure-generic-function returns that generic function.
This means that (in some of the cases) where you used to write:
(add-method 'foo <method>)
you will write
(add-method (ensure-generic-function 'foo) <method>)
There is no doubt that this is more verbose in the cases where you have
to use ensure-generic-function, but I believe it is much clearer.
∂26-Jan-87 1413 Bobrow.pa@Xerox.COM Re: ---
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Jan 87 14:12:38 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 26 JAN 87 12:58:10 PST
Date: 26 Jan 87 12:58 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: ---
In-reply-to: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET's message of 23 Jan
87 15:15:45
To: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
cc: Bobrow.pa@Xerox.COM, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870126-125810-4306@Xerox>
2) There is no lambda-list. It also omits the keyword
:order from the method specifier. defgeneric-options is
extended to store parameters in the generic function. This
can be used to support features like reversed order for
<and> combination if desired.
There is a problem in tying up the parameters of the method
combination to the generic function. If the user has to access
those from the generic function, extensions where there can be
several method combinations defined for the same generic function
will not work. Parameters passed explicitly to the method
combination function avoid this problem.
In both versions of define-method-combination, the parameters passed are
a function of the particular generic-function. a generic-function can
have only one method-combination type -- parametrized or not.
I am not sure that the :around keyword actually simplifies
things. It hides the around mechanism, but seeing the actual code
helps people to get the right model in their minds.
The point here is that we want to make it easy to suport :around
methods, and it is such a common idiom that we want to make it short.
By showing the translation (which people can understand once) we hope to
give people the right model in their minds.
Despite these points, we seem to be converging on this issue.
I take this message as support for including this version of
define-method-combination as the one in the specification. I agree with
Gabriel that this committee should really amke up its mind.
danny
∂26-Jan-87 1605 kahn.pa@Xerox.COM :allocation :none
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Jan 87 15:58:45 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 26 JAN 87 14:34:27 PST
Date: 26 Jan 87 14:33 PST
Sender: kahn.pa@Xerox.COM
From: Ken kahn <kahn.pa@Xerox.COM>
Subject: :allocation :none
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870126-143427-4458@Xerox>
I thought I should explain the original motivation for :allocation
:none. There are two expected uses of it.
1) A subclass implements an inherited slot procedurally (i.e. it defines
accessor methods) and doesn't need any storage set aside. :allocation
:none just saves some space in each instance but has no semantic import
(except maybe with respect to low-level slot access, i.e. slot-value).
2) A slot is not needed by a subclass. Declaring it :allocation :none
is both a cheap way to get an error is the instances really do need it
and again a way to save space in instances.
So I guess I'm agreeing with Moon that the slot continues to exist but
certain kinds of access to it are errors.
To some extent, the value of :allocation :none depends upon the style of
object-oriented programming. One style is to put alot of functionality
in the super-classes which sub-classes turn off. E.g. an
immovable-window is a subclass of ordinary window and needn't waste
space for slots used only in supporting movement.
----- ken
∂26-Jan-87 2056 Moon@STONY-BROOK.SCRC.Symbolics.COM Class-precedence-list computation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 26 Jan 87 20:56:10 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 52426; Mon 26-Jan-87 23:54:29 EST
Date: Mon, 26 Jan 87 23:54 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Class-precedence-list computation
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870126005535.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870126235427.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Status update on this:
Date: Mon, 26 Jan 87 00:55 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Dick, your algorithm does not produce the same results as the Flavors....
the most productive thing for me to do next would be to think about a
coherent statement of that Flavors rule designed to fit into the framework
of Dick's explanation of class precedence computation, where the preorder
treewalk is now.
I've tried several ideas for this but haven't found one that works yet.
I'll keep at it.
I haven't tried coding Danny's algorithm (proposed a month or two ago)
yet. I wonder if it does the same thing as either of these other
algorithms.
I've been playing around with this (code from Gregor's message of Dec 2).
It usually does what I consider the right thing, but sometimes it does
something different from both Gabriel and Flavors; I haven't been able
to boil that down to a small test case yet. The Bobrow algorithm also
goes into an infinite loop in some cases (again, not yet boiled down to
a simple case). I don't know for sure whether it's truly an infinite
loop or just a combinatorial explosion; I gave up after a minute or so
in one case, and after a few seconds in several other cases (normally the
algorithm takes much less than a second).
∂26-Jan-87 2127 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: change-class and class redefinition
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 26 Jan 87 21:27:36 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 52441; Tue 27-Jan-87 00:25:15 EST
Date: Tue, 27 Jan 87 00:25 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: change-class and class redefinition
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870123-114021-2379@Xerox>
Message-ID: <870127002518.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 23 Jan 87 11:40 PST
From: Gregor.pa@Xerox.COM
I like this argument, and am now happy with the change-class, class-changed part of this.
Since we seem to be in agreement, I asked Sonya to put a somewhat cleaned up version
of what I mailed out into the document in the next round of editing. You'll see it
there and can comment further. There are still a few open questions, maybe the right
thing is just to list the open questions in the document and deal with them later.
In this case, I think the open questions are open because no one has an opinion,
rather than because we have too many contradictory opinions.
∂27-Jan-87 0027 RPG CPL Update
To: common-lisp-object-system@SAIL.STANFORD.EDU
I'm also working on finding a New Flavors equivalent that works
within the topological sort framework. I have one such equivalent,
which can be explained in either of two ways. I think I have a second
algorithm that produces the same results as the New Flavors algorithm
which can be described differently from the topological sort algorithms
and the New Flavors algorithm - it is of the form of a certain weird
treewalk and doesn't do multiple depth-first walks.
I'll send out the details once I consult with my algorithms wizard,
which should be tomorrow afternoon.
-rpg-
∂27-Jan-87 0927 Bobrow.pa@Xerox.COM Re: CPL Update
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 Jan 87 09:27:04 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 27 JAN 87 09:26:39 PST
Date: 27 Jan 87 09:26 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: CPL Update
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 27 Jan 87
00:27 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870127-092639-5358@Xerox>
I'm also working on finding a New Flavors equivalent that works
within the topological sort framework. I have one such equivalent,
which can be explained in either of two ways. I think I have a
second algorithm that produces the same results as the New Flavors
algorithm which can be described differently from the topological
sort algorithms and the New Flavors algorithm - it is of the form
of a certain weird treewalk and doesn't do multiple depth-first
walks.
I think that your algorithm would work the same as New Flavors if you
used a last-visited walk, that is used the following algorithm for your
walk to dismbiguate in case of choice. In my hand simulations of your
algorithm it does:
``A last-visited treewalk is defined in terms of the order in which
classes
are visited while performing a process called ``walking from a class.''
The following is a recursive definition of walking from a class. Let C
be
a class and let C1...Cn be its direct superclasses in the local
precedence
order. Nodes are visited unless they WILL BE LATER visited. To walk
from C, first C is visited, then we walk from C1, then we walk from C2,
and so on until we finally walk from Cn.''
This is equivalent to laying out a linearization visiting each class as
many times as you get to it, and removing all but the last occurrence.
(Also sometimes described as left-to-right depth first up to joins.)
I haven't tried coding Danny's algorithm (proposed a
month or two ago) yet. I wonder if it does the same thing as
either of these other algorithms.
I've been playing around with this (code from Gregor's message
of Dec 2). It usually does what I consider the right thing, but
sometimes it does something different from both Gabriel and Flavors
I haven't been able to boil that down to a small test case
yet. The Bobrow algorithm also goes into an infinite loop in some
cases (again, not yet boiled down to a simple case).
It is my belief that Gregor's code was an implementation of my
algorithm, so you need not recode -- I would be very interested in a
simple example for Gregors code, or even a complex one that I could look
at and analyze.
General conclusion. In all the cases I have seen, I have agreed that
the New Flavors ordering is good. I believed my algorithm also computed
it. Dave, could you try my variation on Gabriels algorthm against the
new Flavors system?
danny
∂27-Jan-87 1112 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: ---
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 27 Jan 87 11:10:37 PST
Received: from ti-csl by csnet-relay.csnet id af00212; 27 Jan 87 13:18 EST
Received: from dsg (juliett.ARPA) by tilde id AA20573; Tue, 27 Jan 87 11:33:35 cst
Received: FROM Jenner BY dsg Via CHAOS-NET with CHAOS-MAIL; 27-Jan-87 11:33:04
Message-Id: <2747756002-313686@Jenner>
Date: 27-Jan-87 11:33:22
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
To: Danny Bobrow <Bobrow.pa@XEROX.COM>
Cc: common-lisp-object-system@SU-AI.ARPA
Subject: Re: ---
In-Reply-To: In-Reply-To: Msg of 26-Jan-87 14:58:00 from Danny Bobrow <Bobrow.pa@Xerox.COM>Msg of 26-Jan-87 14
Date: 26-Jan-87 14:58:00
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
2) There is no lambda-list. It also omits the keyword
:order from the method specifier. defgeneric-options is
extended to store parameters in the generic function. This
can be used to support features like reversed order for
<and> combination if desired.
There is a problem in tying up the parameters of the method
combination to the generic function. If the user has to access
those from the generic function, extensions where there can be
several method combinations defined for the same generic function
will not work. Parameters passed explicitly to the method
combination function avoid this problem.
In both versions of define-method-combination, the parameters passed are
a function of the particular generic-function.
That's true but david's one allows for extensions, yours does not. If
the mechanism that fetches the parameters is encapsulated, the
parameters don't have to be a function of the generic function only.
If the user has to get them explictly from the generic function slot, it
becomes apparent that they have to be a function of the particular
generic-function only.
A generic-function can have only one method-combination type --
parametrized or not.
Well that's what is in the standard. I consider this assumption being
a simplification of a more general model. I understand that we don't
want to put the general model in the standard (Size, complexity.....)
but we can't lock the standard in a mode where only the simplistic model
can be supported without incompatibilities.
I am not sure that the :around keyword actually simplifies
things. It hides the around mechanism, but seeing the actual code
helps people to get the right model in their minds.
The point here is that we want to make it easy to suport :around
methods, and it is such a common idiom that we want to make it short.
By showing the translation (which people can understand once) we hope to
give people the right model in their minds.
I don't care that much about this point. Either way would be fine with
me.
Despite these points, we seem to be converging on this issue.
I take this message as support for including this version of
define-method-combination as the one in the specification. I agree with
Gabriel that this committee should really amke up its mind.
You're jumping to conclusion. Convergence means that each additional
proposal has negligible added value.If we truly converge, we could leave
David's write-up because yours wouldn't bring much more. See, the
argument goes both ways!
More seriously, I think that David's proposal augmented with predicates
looks good to me, I would prefer it to yours for the reasons I brought
earlier.
Patrick.
∂27-Jan-87 1207 RPG CPL Computation
To: common-lisp-object-system@SAIL.STANFORD.EDU
As I've mentioned earlier, I wasn't interested in proposing a new
definition of the CPL computation different from what Flavors presents but
in proposing a clear way of describing it.
I took Moon's suggestion and looked for a different ``tiebreaker'' from
preorder treewalk. I have a simple way to describe it, but the naive
implementation has bad running behavior. The fast version is describable,
but the description is horrendous. I think we want to consider what this
all means once the algorithms are presented.
The algorithm is precisely as before, but when the topological sort would
nondeterministically select one class from among a set of equally good
ones, you choose based on a last-visited preorder treewalk.
A last-visited preorder treewalk is defined in terms of the order in which
classes are visited while performing a process called ``walking from a
class.'' The following is a recursive definition of walking from a class.
Let C be a class and let {C1...Cn} be its direct superclasses in the local
precedence order. To walk from C, first C is visited, then we walk from
C1, then we walk from C2, and so on until we finally walk from Cn.
If a class has been visited before, you ignore that visit. That is,
the order is the order in which the last visits to a node are made.
Normally, one computes the preorder treewalk order as a number attached to
the class. Again normally, this number is computed by performing the
preorder treewalk and INCFing a counter. In a preorder treewalk, when a
class already has a preorder number, you do not re-visit that class; the
modification to normal preorder treewalk to obtain last-visited preorder
treewalk is to eliminate this last pruning. The tiebreaker simply looks
at these preorder numbers, choosing the class with the smallest preorder
number.
Notice that a lot of pruning might have been done by the original preorder
walk and that the last-visited preorder walk eliminates all of the
pruning.
Here is some crufty code to compute the normal preorder number into
a slot of the class called the PREORDER:
(defun preorder-walk (class)
(cond ((< 0 (preorder class))) ;already visited
(t (setf (preorder class) (incf *preorder-counter*))
(dolist (superclass (direct-superclasses class))
(preorder-walk superclass)))))
Here is the modified code:
(defun lv-preorder-walk (class)
(setf (preorder class) (incf *preorder-counter*))
(dolist (superclass (direct-superclasses class))
(lv-preorder-walk superclass)))
This is, of course, less efficient than the previous code, though it looks
simpler. One can get a fast algorithm by doing what could be called a
reversed reversed postorder treewalk (``moonwalk,'' for short).
We define reversed postorder treewalk and then modify that to be reversed
reversed postorder treewalk.
A reversed postorder treewalk is defined in terms of the order in which
classes are visited while performing a process called ``walking from a
class.'' The following is a recursive definition of walking from a class.
Let C be a class and let {C1...Cn} be its direct superclasses in the local
precedence order. Classes are visited unless they have already been
visited. To walk from C, first we walk from Cn, then we walk from Cn-1,
and so on until we finally walk from C1. Finally we visit C. A reversed
reversed postorder treewalk visits classes in precisely the reverse order
that they are visited in a reversed postorder treewalk.
Implementationally, moonwalk isn't too bad. You place reversed postorder
numbers on each class at or above the class of interest, and ties are
broken by selecting the class with the largest reversed postorder number
(note that we chose the smallest number in the preorder tiebreaker).
Selecting the largest effects the second reversing.
Here is the code to do this:
(defun walk (class)
(cond ((< 0 (rpostorder class)))
(t (dolist (superclass (reverse (direct-superclasses class)))
(walk superclass))
(setf (rpostorder class) (incf *counter*)))))
This algorithm works on all of the examples I sent before plus the
two killers Moon sent Sunday.
The question now becomes: Is this what we really want? I claim that
it doesn't matter too much what the tiebreaker is, because it is always
possible to reformulate the lattice and use direct superclasses to
achieve the desired effect. The fact the there are millions of flavors
that use the moonwalk tiebreaker doesn't support the claim that
the moonwalk tiebreaker is right: Perhaps the flavors have been carefully
crafted to inherit properly.
The explicit local precedence orders are the means by which programmers
specify the ordering they want. The tiebreaker simply makes the total
order well-defined. The tiebreaker is not intended to be a ``model''
of the class precedence list. If the topological sort produces a unique
order, that order is intuitive; the cases where tiebreaking happens is
ad hoc and is no intuitive.
In the spirit of trying to figure out the New Flavors algorithm in order
to be able to present it well, my algorithms wizard and I have tried come
up with a more easily explainable algorithm that mimics the New Flavors
and does not have topological sort as an explicit part of it. We failed,
though we have not yet written down an example for which it fails.
[I only mention this because I promised to show this algorithm in my last
message.]
Finally, I'm not sure that the first of Moon's killers has a very intuitive
Flavors order. Here it is again:
(DEFCLASS PTEST1 (PTEST2 PTEST3 PTEST5) ())
(DEFCLASS PTEST2 (PTEST5) ())
(DEFCLASS PTEST3 (PTEST4) ())
(DEFCLASS PTEST4 () ())
(DEFCLASS PTEST5 () ())
The Flavors order is (ptest1 ptest2 ptest3 ptest4 ptest5).
Why is ptest4 before ptest5? Here's what the thing looks like:
top------
| |
pt4 |
| |
|-----------pt5
| | /
pt2 pt3 /
\ | /
\ | /
pt1
pt5 is a direct superclass of pt1 and pt4 isn't. One could argue that pt5
is the last of the direct superclasses, so it should come after the
earlier direct superclasses and all of their superclasses; in this case
you get to pt4 first because it is above pt3, which precedes pt5. But,
does being mentioned first in a defclass count for anything? If so, you
get to pt5 by passing through the first of the direct superclasses of pt1
(pt1 to pt2 to pt5) whereas you get to pt4 by passing through the second
of the direct supeclasses of pt1 (pt1 to pt3 to pt4), and there are
exactly the same number of intermediate classes. Everything says pt5
should precede pt4, but Flavors doesn't. I believe this to be a serious
problem.
Finally, my algorithms wizard and I studied the New Flavors CPL
computation description and think there is a performance problem with the
algorithm it describes. Consider the following graph of 4n+1 classes:
(defclass Ai (Bi Ci) ())
(defclass Bi (Di Ai+1) ())
(defclass Ci (Di) ())
(defclass Di () ())
for 0 <= i < n.
Here are the classes for n=2.
(defclass a0 (b0 c0) ())
(defclass b0 (d0 a1) ())
(defclass c0 (d0) ())
(defclass d0 () ())
(defclass a1 (b1 c1) ())
(defclass b1 (d1 a2) ())
(defclass c1 (d1) ())
(defclass d1 () ())
The New Flavors algorithm, as described, seems to take n+1 passes, though
there is exactly one total order possible.
Given that reversed reversed postorder treewalk (or last-visited preorder)
is the tiebreaker, that there is at least one suspicious Flavors-order
example, that people can formulate their lattices as they want to get the
right inheritance, that there is no intuition to any order beyond what the
topological sort gives you, and there is a possible performance problem
with the algorithm described in the New Flavors document, I have now
flipped my bit on this issue from wanting to mimic the Flavors order
to insisting on preorder tiebreaker with topological sort.
-rpg-
∂27-Jan-87 1430 Bobrow.pa@Xerox.COM Re: CPL Computation
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 Jan 87 14:29:59 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 27 JAN 87 13:00:35 PST
Date: 27 Jan 87 13:00 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: CPL Computation
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 27 Jan 87
12:07 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870127-130035-5654@Xerox>
Given that reversed reversed postorder treewalk (or
last-visited preorder) is the tiebreaker, that there is at least
one suspicious Flavors-order example, that people can formulate
their lattices as they want to get the right inheritance, that
there is no intuition to any order beyond what the topological sort
gives you, and there is a possible performance problem with the
algorithm described in the New Flavors document, I have now flipped
my bit on this issue from wanting to mimic the Flavors order to
insisting on preorder tiebreaker with topological sort.
Everything says pt5 should precede pt4, but Flavors doesn't. I
believe this to be a serious problem.
I don't believe this. The argument for the New Flavors (and
Bobrow/Kiczales) ordering is the following. If the user has a class (a
mixin), and for reasons known to them splits that class into two classes
e.g. (p3' into p3 and p4), with no other references, there should be no
chance of any interaction with any other class used as a mixin. Hence
one wants all superclasses of a class to follow as soon as possible
after the class they are referred to. As soon as possible is what you
get from last-visited pre-order walk.
Moon-walk (which is what is in B/K) is a reasonable implementation of
"last-visited pre-order walk". We don't have to describe the algorithm
and the effect in one paragraph. The effect is a linearization of a
full tree walk maintaining only the last visit. The computation
computes it from the rear to avoid revisits.
danny
∂27-Jan-87 1432 Bobrow.pa@Xerox.COM Re: ---
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 Jan 87 14:30:11 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 27 JAN 87 13:05:43 PST
Date: 27 Jan 87 13:05 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: ---
In-reply-to: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET's message of 27 Jan
87 11:33:22
To: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
cc: Bobrow.pa@Xerox.COM, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870127-130543-5661@Xerox>
A generic-function can have only one method-combination
type -- parametrized or not.
Well that's what is in the standard. I consider this assumption
being a simplification of a more general model. I understand that
we don't want to put the general model in the standard (Size,
complexity.....) but we can't lock the standard in a mode where
only the simplistic model can be supported without
incompatibilities.
To get other kinds of extensions, one uses the meta-object protocol,
which in this case consists of defining your own method on
compute-effective-method. Since this is called by the system when
generic function is called with a set of arguments, the only thing it
can depend on is information from the generic function (and of course
the argument types). The issue is whether that information is extracted
by the system and made an argument of the method, or extracted in the
method. I have suggested that extracting it in the method is the
general way to do it.
I take this message as support for including this version of
define-method-combination as the one in the specification. I
agree with Gabriel that this committee should really amke up its
mind.
You're jumping to conclusion. Convergence means that each
additional proposal has negligible added value.
I really meant this as a prod to get us to think about this some more.
We need to be talking about it.
danny
∂27-Jan-87 1752 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: ---
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jan 87 17:50:57 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 54288; Tue 27-Jan-87 20:49:39 EST
Date: Tue, 27 Jan 87 20:49 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: ---
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870127-130543-5661@Xerox>
Message-ID: <870127204942.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 27 Jan 87 13:05 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
A generic-function can have only one method-combination
type -- parametrized or not.
Well that's what is in the standard. I consider this assumption
being a simplification of a more general model. I understand that
we don't want to put the general model in the standard (Size,
complexity.....) but we can't lock the standard in a mode where
only the simplistic model can be supported without
incompatibilities.
To get other kinds of extensions, one uses the meta-object protocol,
which in this case consists of defining your own method on
compute-effective-method. Since this is called by the system when
generic function is called with a set of arguments, the only thing it
can depend on is information from the generic function (and of course
the argument types). The issue is whether that information is extracted
by the system and made an argument of the method, or extracted in the
method. I have suggested that extracting it in the method is the
general way to do it.
That is not really what you have suggested. You suggested extracting it in
the define-method-combination. That's entirely different from extracting
it in a method that is defined by someone using the meta-object protocol.
Your suggestion would mean that define-method-combination forms would not
be portable between systems that have only one method combination type per
generic-function and systems that are more general. What I think Patrick
is suggesting is that the extension to allow more general selection of a
method-combination type should be orthogonal to the method-combination
types themselves.
∂27-Jan-87 1801 RPG Elaboration on the Non-intuitiveness of New Flavors Algorithm...
To: common-lisp-object-system@SAIL.STANFORD.EDU
...and other related issues.
Remember the funny little configuration of classes mentioned
in an earlier message
(defclass Ai (Bi Ci) ())
(defclass Bi (Di Ai+1) ())
(defclass Ci (Di) ())
(defclass Di () ())
for 0 <= i < n.
Here's what it looks like:
A1
D0 /
| \ /
| \/
| /\
| / \
B0 C0
\ /
\ /
\/
A0
Suppose we are following the New Flavors description of how to compute the
CPL for A0. We start walking through this in depth-first manner starting
at A0. We visit/output A0, visit/output B0, visit D0, visit A1,
visit/output C0, and then visit/output D0. There is no path in depth-first
order with which to get to A1 again, so the first depth-first pass is
over. We notice A1 has not been output and walk it again, outputting A1
last. If A1 is the root of another copy of this, we cannot visit up
through it on the first pass.
If there are classes to the right of A0, they wil be visited and probably
output during the first pass. When the second pass is made, A1 will
be output.
Let's call this configuration the ``MeLast.''
Now consider the following configuration:
T1 T2 T3
| | |
D E F
\ | /
\ | /
\ | /
\|/
C
where C is a class and T1, T2, T3 are independent lattices, except for a
common top. What does intuition say? It says that all of T1 should be
together, all of T2 should be together, and all of T3 should be together,
each group in in some order relative to one another, and the order within
each group unknown. One could argue T1 should precede T2 should precede
T3, but I won't. Suppose that T1 has a MeLast in it, and neither T2 nor T3
does. Then some part of T1 - namely A0, B0, C0, and D0 - will come
early on, then parts of T2 and T3, and finally A1 will be last.
Similar situations hold for T2 and T3, but in all cases, A1 will be last,
assuming there are no other MeLast-like configurations in the T groups.
The intuition is gone.
Here is an example:
MeLast
|
X Y Z
\ | /
\|/
W
The New Flavors order is:
W,X,Y,A0,B0,C0,D0,Z,A1
The gabriel order is:
W,X,Y,A0,B0,C0,D0,A1,Z
Notice that in the gabriel order, the Y/MeLast guys are together
between Y and Z.
The existence of a MeLast configuration is purely an artifact of the
multiple passes that the New Flavors CPL computation does. If it had
a way to remember to redo A1 as soon as its predecessor, D0, was cleared
up, it would not need to make another pass through the lattice.
The MeLast configuration also proves that no algorithm based on
topological sort with a tiebreaker that is like a single-pass,
single-stack treewalk is equivalent to the New Flavors computation. I
haven't thought through the exact constraints, but preorder, reversed
reversed postorder, and things like that as the tiebreaker in conjunction
with topological sort cannot be the same as New Flavors, because they will
put classes in the groups T1, T2, and T3 together.
This increases the strength of my belief that the New Flavors algorithm is
not suitable for the CLOS standard.
-rpg-
∂27-Jan-87 1805 Bobrow.pa@Xerox.COM Re: CPL Update
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 Jan 87 18:04:20 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 27 JAN 87 17:06:27 PST
Date: 27 Jan 87 17:06 PST
From: Bobrow.pa@Xerox.COM
Subject: Re: CPL Update
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870127-170627-5999@Xerox>
I'm also working on finding a New Flavors equivalent that works
within the topological sort framework. I have one such equivalent,
which can be explained in either of two ways. I think I have a
second algorithm that produces the same results as the New Flavors
algorithm which can be described differently from the topological
sort algorithms and the New Flavors algorithm - it is of the form
of a certain weird treewalk and doesn't do multiple depth-first
walks.
I think that your algorithm would work the same as New Flavors if you
used a last-visited walk, that is used the following algorithm for your
walk to dismbiguate in case of choice. In my hand simulations of your
algorithm it does:
``A last-visited treewalk is defined in terms of the order in which
classes
are visited while performing a process called ``walking from a class.''
The following is a recursive definition of walking from a class. Let C
be
a class and let C1...Cn be its direct superclasses in the local
precedence
order. Nodes are visited unless they WILL BE LATER visited. To walk
from C, first C is visited, then we walk from C1, then we walk from C2,
and so on until we finally walk from Cn.''
This is equivalent to laying out a linearization visiting each class as
many times as you get to it, and removing all but the last occurrence.
(Also sometimes described as left-to-right depth first up to joins.)
I haven't tried coding Danny's algorithm (proposed a
month or two ago) yet. I wonder if it does the same thing as
either of these other algorithms.
I've been playing around with this (code from Gregor's message
of Dec 2). It usually does what I consider the right thing, but
sometimes it does something different from both Gabriel and Flavors
I haven't been able to boil that down to a small test case
yet. The Bobrow algorithm also goes into an infinite loop in some
cases (again, not yet boiled down to a simple case).
It is my belief that Gregor's code was an implementation of my
algorithm, so you need not recode -- I would be very interested in a
simple example for Gregors code, or even a complex one that I could look
at and analyze.
General conclusion. In all the cases I have seen, I have agreed that
the New Flavors ordering is good. I believed my algorithm also computed
it. Dave, could you try my variation on Gabriels algorthm against the
new Flavors system?
∂27-Jan-87 1854 Bobrow.pa@Xerox.COM Re: ---
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 Jan 87 18:54:10 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 27 JAN 87 18:23:40 PST
Date: 27 Jan 87 18:23 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: ---
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 27 Jan 87 20:49 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870127-182340-6111@Xerox>
The issue is whether that information is extracted by
the system and made an argument of the method, or extracted in
the method. I have suggested that extracting it in the method
is the general way to do it.
That is not really what you have suggested. You suggested
extracting it in the define-method-combination.
I suggest doing it in both. That is, any information other than the
combination-type (e.g. standard , and) which selects a method is
extracted from the generic function.
Your suggestion would mean that define-method-combination forms
would not be portable between systems that have only one method
combination type per generic-function and systems that are more
general. What I think Patrick is suggesting is that the extension
to allow more general selection of a method-combination type should
be orthogonal to the method-combination types themselves.
I don't understand how a generic function can have more than one
method-combination type. I also don't understand your last sentence at
all.
danny
∂27-Jan-87 1857 Bobrow.pa@Xerox.COM Re: Elaboration on the Non-intuitiveness of New Flavors
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 Jan 87 18:54:20 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 27 JAN 87 18:31:18 PST
Date: 27 Jan 87 18:31 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Elaboration on the Non-intuitiveness of New Flavors
Algorithm...
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 27 Jan 87
18:01 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870127-183118-6120@Xerox>
Wow. I found your example clever. And I now believe also that
last-vist disambiguation of topological sort is the most intuitive, and
not the New Flavors one (and that the B-K code will produce the same
results ). I wonder if the case that Moon found for ours that was
different than new Flavors was of the Me-last sort.
danny
∂27-Jan-87 1914 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: ---
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 27 Jan 87 19:14:20 PST
Received: from ti-csl by csnet-relay.csnet id aa05659; 27 Jan 87 20:03 EST
Received: from dsg (juliett.ARPA) by tilde id AA04554; Tue, 27 Jan 87 17:39:49 cst
Received: FROM Jenner BY dsg Via CHAOS-NET with CHAOS-MAIL; 27-Jan-87 17:38:49
Message-Id: <2747777986-278997@Jenner>
Date: 27-Jan-87 17:39:46
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
To: Danny Bobrow <Bobrow.pa@XEROX.COM>
Cc: common-lisp-object-system@SU-AI.ARPA
Subject: Re: ---
In-Reply-To: In-Reply-To: Msg of 27-Jan-87 15:05:00 from Danny Bobrow <Bobrow.pa@xerox.com>Msg of 27-Jan-87 15
Date: 27-Jan-87 15:05:00
From: Danny Bobrow <Bobrow.pa@xerox.com>
A generic-function can have only one method-combination
type -- parametrized or not.
Well that's what is in the standard. I consider this assumption
being a simplification of a more general model. I understand that
we don't want to put the general model in the standard (Size,
complexity.....) but we can't lock the standard in a mode where
only the simplistic model can be supported without
incompatibilities.
To get other kinds of extensions, one uses the meta-object protocol,
which in this case consists of defining your own method on
compute-effective-method. Since this is called by the system when
generic function is called with a set of arguments, the only thing it
can depend on is information from the generic function (and of course
the argument types). The issue is whether that information is extracted
by the system and made an argument of the method, or extracted in the
method. I have suggested that extracting it in the method is the
general way to do it.
I agree with the fact than one can define its own
compute-effective-method, the issue has to do with modularity.
Compute-effective-method has to find the list of all the method that can
be called, find the method combination method, call it to come up with the
code for the effective method. We need to keep those operations as
independent as possible. If we supply the information as an argument to
the method combinator, the user writing a method combination method does
not have to worry about how the information was obtained. Different
implementations of compute-effective-method will be able to call the
same method combinator even if they use different ways to come up with
the method combination method. It seems more modular and more general
than extracting the information in the method.
Maybe David has some more (convincing?) arguments.
Patrick.
∂27-Jan-87 2003 Moon@RIVERSIDE.SCRC.Symbolics.COM :allocation :none
Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jan 87 20:02:44 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 96592; Tue 27-Jan-87 23:00:59 EST
Date: Tue, 27 Jan 87 23:01 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: :allocation :none
To: Common-Lisp-Object-System@sail.stanford.edu
cc: CLOS@STONY-BROOK.SCRC.Symbolics.COM
In-Reply-To: <870126-143427-4458@Xerox>
Message-ID: <870127230108.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 26 Jan 87 14:33 PST
From: Ken kahn <kahn.pa@Xerox.COM>
I thought I should explain the original motivation for :allocation
:none. There are two expected uses of it.
1) A subclass implements an inherited slot procedurally (i.e. it defines
accessor methods) and doesn't need any storage set aside. :allocation
:none just saves some space in each instance but has no semantic import
(except maybe with respect to low-level slot access, i.e. slot-value).
2) A slot is not needed by a subclass. Declaring it :allocation :none
is both a cheap way to get an error if the instances really do need it
and again a way to save space in instances.
So I guess I'm agreeing with Moon that the slot continues to exist but
certain kinds of access to it are errors.
To some extent, the value of :allocation :none depends upon the style of
object-oriented programming. One style is to put alot of functionality
in the super-classes which sub-classes turn off. E.g. an
immovable-window is a subclass of ordinary window and needn't waste
space for slots used only in supporting movement.
In Flavors, we spent a lot of time some years ago discovering that that
style doesn't work very well. It worked out a lot better to split the
superclass into separate modules and then inherit whichever ones are
wanted. I haven't thought about it real deeply, but I think the Common
Lisp object system is similar enough to Flavors that it will work out
the same way.
If you believe this, maybe we should get rid of :allocation :none, since
it seems to make slot inheritance a lot harder to document and to
understand.
∂27-Jan-87 2011 Moon@RIVERSIDE.SCRC.Symbolics.COM symbols are not generic functions
Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jan 87 20:06:38 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 96593; Tue 27-Jan-87 23:04:57 EST
Date: Tue, 27 Jan 87 23:05 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: symbols are not generic functions
To: Common-Lisp-Object-System@Sail.Stanford.edu
In-Reply-To: <870126-141351-4399@Xerox>
Message-ID: <870127230506.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 26 Jan 87 14:12 PST
From: Gregor.pa@Xerox.COM
symbols are not generic functions, they can only be used to name a
generic function. The primitive levels of the meta-interpreter deal
with generic-function objects. symbols as names of generic functions
are a convenience provided by defmethod, defmethod-setf
defgeneric-options etc.
Consequently, I would like to propose the following change.
I suggest that add-method, remove-method and get-method be changed to
require that their first argument be a generic-function object. Along
with this I would like to introduce a new function which will provide
the functionality I am proposing we remove in a more rational way.
This change is okay with me. See comments below.
ensure-generic-function (or some such name) takes a symbol, or a list
(SETF <symbol>) and makes sure there is a generic function of the
default kind (standard-generic-function) "there". For convenience,
ensure-generic-function returns that generic function.
I don't completely understand. Suppose symbol-function of the symbol
is already a generic function, but it is of a different class than the
kind that you get by default, because someone is using generic-function
meta-objects. Would ensure-generic-function accept that generic
function, signal an error, or clobber it with a generic function of
the default kind?
Also, does ensure-generic-function ever alter the symbol-function of
a symbol, or is it just a side-effect free coercion? If the latter,
it might be cleaner to use the existing COERCE function, thus
(add-method (coerce <arg> 'generic-function) <method>).
This means that (in some of the cases) where you used to write:
(add-method 'foo <method>)
you will write
(add-method (ensure-generic-function 'foo) <method>)
There is no doubt that this is more verbose in the cases where you have
to use ensure-generic-function, but I believe it is much clearer.
∂27-Jan-87 2116 Moon@STONY-BROOK.SCRC.Symbolics.COM Danny's new version of define-method-combination
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jan 87 21:16:27 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 54412; Wed 28-Jan-87 00:05:45 EST
Date: Wed, 28 Jan 87 00:05 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Danny's new version of define-method-combination
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870120-122111-2214@Xerox>,
<870120-131551-2295@Xerox>
Message-ID: <870128000529.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
I said I wasn't going to think about method-combination any more this
month, but I changed my mind. The indented messages below are excerpted to
show just enough context for my comments to make sense. In the interests
of getting the document finished soon, for each point, after general
discussion I make a suggestion for what to do; naturally I'm more than
willing to listen to arguments that my suggestions are wrong.
Date: 20 Jan 87 12:11 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
1) There is only one define-method-combination form.
I don't think the short form is vitally important, but until we converge
on all details of the long form it's difficult to tell how much syntactic
verboseness and error-proneness the short form will save. I suggest that
for right now a boldface note be added to the document saying that the
short form is still under discussion and there is a good chance it will
go away in a future revision.
2) There is no lambda-list. It also omits the keyword :order from the
method specifier. defgeneric-options is extended to store parameters
in the generic function. This can be used to support features like
reversed order for <and> combination if desired.
I agree with Patrick's argument that storing parameters in the generic
function won't work.
There is a more general philosophical issue here. Symbolics has agreed to
the approach of making a lean proposal, containing only features that are
truly necessary and that are well-understood. One can see from reading the
document that this policy hasn't been carried out perfectly uniformly, but
it's the direction we're aiming. There are a number of extensions that we
feel are important in the industrial real world, but that we agree don't
belong in the standard right now. If these extensions prove worthwhile,
they might be implemented by individual implementations and then eventually
added to the standard. I consider it important to design the lean standard
so that such extensions can be added smoothly and painlessly, without
making incompatible changes to the original standard. This means that some
design choices, which could go either way when considered in isolation,
need to go a certain way in order to leave room for possible extensions.
Is this agreeable to the other participants?
This is the reason for the lambda-list. Having to say () now is relatively
painless, but adding a lambda-list in the future would be difficult. In
fact the lambda-list also turns out to be a better way to provide access to
the generic-function object than any other I've thought of.
I would be agreeable to removing the :order keyword if a lean standard is
paramount, although it seems to add only minimal complexity and I've seen
reversed order of method specificity used quite a lot.
I suggest not changing anything here. Alternatively, :order could be
removed.
3) It is syntactically distinguishable from the current Flavors
version of define-method-combination, and hence allows backwards
compatiblity.
Current Flavors users will bless you.
4) It uses the keyword :call-next-method instead of :around in
make-method-call.
This is okay with me.
[A later message from Danny said:]
Because :operator and :call-next-method (nee :around) cannot both
appear, I suggest that the syntax of make-method-call be
(make-method-call method-list &optional
(operator 'progn)
(identity-with-one-argument (eq operator 'progn)))
Where if operator has the value :call-next-method, it has the same
effect as previously providing that argument with t as its value.
I'm opposed to using optional arguments instead of keyword arguments,
because it makes extensibility much more awkward. Using a special
value for the :operator argument instead of a :call-next-method
argument would be okay with me, although I suspect it will be difficult
to document in a way that does not cause confusion.
I suggest changing :around to :call-next-method here, but flushing :around
and saying :operator 'call-next-method (no colon) would be okay too.
Flushing the idea of controlling it with an argument and going back to a
second function, named make-next-method-call or something, would be okay
too. Does anyone have a strong preference for one or another of these?
{method-combination-option} :=combination-keyword value
The list of method-combination options is optional, and is
distinguished from a form because it starts with a keyword.
We have this syntax for method-combination options in Flavors and I think
it is grotesque. I suggest not including this.
The keyword options supported are:
{\bf :documentation} {\it string\/} documents the method-combination
type.
I don't see why we shouldn't use the same syntax as defmacro for
documentation strings.
{\bf :around} {\it boolean\/}
If the argument is true (not {\bf nil}),
then the form returned by the body of define-method-combination
is augmented to support :around methods.
I comment on this below, in connection with Gregor's comments on it.
The variable {\it generic-function\/} is available in the body forms of the
combination definition.
That's how we do it in Flavors (the variable name is slightly different)
and I think it is grotesque. It's usually better to let the programmer
choose her own names for variables. I suggest not doing this, although
I don't feel very strongly about it.
Date: 20 Jan 87 13:15 PST
From: Gregor.pa@Xerox.COM
I like the new :around method-combination option. I think this will
make it easier for people to deal with :around methods. We might want
to think about changing the "sense" of this option, or changing the
default, so that aroundification happens by default.
I agree that once it's a yes/no option, it makes sense to have it turned on
by default. The next logical step is to say that if you want to turn it
off, you should be operating at the meta-object level. Do you ever feel
like you're going around in circles? What got us to :around methods in the
first place was you guys' dislike of Flavors whoppers, which cannot be
turned off. (Obviously if Flavors had meta-objects, whoppers could be
turned off at the meta-object level.)
I have two suggestions here. Either one is okay with me:
(1) Make it a method-group keyword option. Thus you say
((around (:around) :call-next-method t) ...other method groups...)
(2) Decide the existing mechanism of two nested calls to make-method-call
is concise enough.
I understand the motivation for allowing a predicate instead of the
templates. I think that motivation should be presented explicitly since
without it, the predicate seems like uneeded complexity.
I agree. Danny, could you write a paragraph about this? (Am I remembering
correctly that you invented the idea of putting the predicate here?)
I don't really like the fact that information is communicated to
make-method-call using special variables. I thought having
make-method-call be a lexically bound function was much more elegant,
and much more in keeping with the lexically scoped way of doing things.
It's a difficult judgement call. What convinced me was that if error
reporting is going to use the Common Lisp condition handling standard, that
inherently involves dynamic variables, so there is nothing to be gained by
making make-method-call not use dynamic variables. I suggest leaving this
the way it is.
I don't really like method-combination-error and invalid-method-error.
They just add complexity to this part of the proposal to make up for the
fact that the error system has not been adopted yet. There are many
parts of the object system which want to signal special kinds of errors,
we don't have special functions for all of them.
This is the first place where we have a hook for programmer-defined
functions, and those functions have to report errors in a standard way.
Perhaps there will be others in the meta-object protocol, but so far there
aren't any others.
Perhaps what we should
do is assume the error system is going to be accepted (seems likely),
and then talk about what kind of error is signalled by each part of the
object system. This seems more reasonable than introducing a bunch of
error functions which will just have to be removed when the error
proposal is adopted, or worse yet supported as backwards compatibility
for life.
We've found that it's often a good idea to provide a function as an
abstraction, even when all that function does is signal a condition.
The name of the condition can be the same as the name of the function,
so that there aren't any extra names to document. This is what I had
in mind here, rather than making a kludge to cope with not having a
standard condition system yet.
I suggest leaving this the way it is except for documenting the rationale
better.
I still don't like calling the default kind of method combination
standard. I would prefer if we called it default, in fact, it might be
better to call it daemon-with-around or some other descriptive name.
I disagree. I really liked Danny's suggestion of calling it standard. As
you know, I think all the predefined objects that are used by default if
you don't make your own should be named standard-xxx (standard-class,
standard-method, etc.) I suggest naming it either standard or
standard-method-combination.
What method combination types will we say are defined? There is a
definite package problem here. We should probably include some comment
on it in the spec. A user can't very well go and do
define-method-combination of lisp:and. If they do it "differently" they
could break the system or some other application. I think the examples
should be re-worked to show users defining method-combinations whose
names are symbols which are not in the lisp package.
This is a hard problem. It relates to modularity and to the difficulty of
legislating programming styles in standards.
It's true that redefining lisp:and differently will break other programs.
A good programming environment will detect this and won't let it go
unchallenged, but if lisp:and is predefined in some environments and not in
others, so that every portable program has to define it, that doesn't help.
It's really not a good idea for every program to redefine and method
combination for itself, with its own name -- that just leads to a Tower of
Babel. On the other hand, not everyone seems to agree that there should be
a library of a dozen or so useful predefined method combination types.
One answer is for that library to be available, but not necessary to be
preloaded in all implementations. Then the portable programmer can load
it if it is not already loaded, but doesn't have to reinvent it. Discouraging
programmers from defining a method-combination type named lisp:and that
does something different, e.g. Prolog unification, is fine with me, since
I believe it's good style for a method-combination type with the same name
as an operator to be derived from that operator in the obvious way.
I suggest that the document should mention this issue but that the name
of and method combination in the example should still be and.
∂27-Jan-87 2117 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: ---
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jan 87 21:16:56 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 54417; Wed 28-Jan-87 00:14:55 EST
Date: Wed, 28 Jan 87 00:14 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: ---
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870127-182340-6111@Xerox>
Message-ID: <870128001434.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 27 Jan 87 18:23 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The issue is whether that information is extracted by
the system and made an argument of the method, or extracted in
the method. I have suggested that extracting it in the method
is the general way to do it.
That is not really what you have suggested. You suggested
extracting it in the define-method-combination.
I suggest doing it in both. That is, any information other than the
combination-type (e.g. standard , and) which selects a method is
extracted from the generic function.
Your suggestion would mean that define-method-combination forms
would not be portable between systems that have only one method
combination type per generic-function and systems that are more
general. What I think Patrick is suggesting is that the extension
to allow more general selection of a method-combination type should
be orthogonal to the method-combination types themselves.
I don't understand how a generic function can have more than one
method-combination type.
It would be an upward-compatible extension to the standard. One way to do
it was proposed by Patrick in his message of 31 October. Another way, which
unfortunately only works for classical methods, exists in Flavors now.
I also don't understand your last sentence at all.
I hope Patrick's latest message clarified it. I was guessing at his
suggestion but he said it himself, about modularity and keeping the
various operations as independent as possible.
∂27-Jan-87 2222 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: CPL Update
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jan 87 22:20:43 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 54454; Wed 28-Jan-87 01:19:19 EST
Date: Wed, 28 Jan 87 01:19 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: CPL Update
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870127-092639-5358@Xerox>
Message-ID: <870128011901.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 27 Jan 87 09:26 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
I think that [Dick's] algorithm would work the same as New Flavors if you
used a last-visited walk....
Dave, could you try my variation on Gabriels algorthm against the
new Flavors system?
I think this was the first or second modification of Gabriel's algorithm
that I tried yesterday. The function is named Gabriel-3, but it looks
like I never finished writing Gabriel-2. Unfortunately I had too many
other things to do today to follow up on this as I ought to have.
Looking back over my notes, I don't have any cases jotted down where
this modified Gabriel performs differently from Bobrow (Gregor's code),
except when the latter seemed to go into an infinite loop. However, I
compared them "exhaustively" just now and found a few cases where they
produce different results. I haven't boiled that down to a simple,
understandable case yet, though.
I do have some cases where both Gabriel-3 and Bobrow produce a different
answer from Flavors, but I haven't finished figuring out what's going on
there yet. The difference might not be real.
∂27-Jan-87 2234 Moon@STONY-BROOK.SCRC.Symbolics.COM CPL Computation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jan 87 22:31:53 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 54462; Wed 28-Jan-87 01:30:37 EST
Date: Wed, 28 Jan 87 01:30 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: CPL Computation
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 27 Jan 87 15:07 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870128013024.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 27 Jan 87 1207 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Finally, my algorithms wizard and I studied the New Flavors CPL
computation description and think there is a performance problem with the
algorithm it describes. Consider the following graph of 4n+1 classes:
(defclass Ai (Bi Ci) ())
(defclass Bi (Di Ai+1) ())
(defclass Ci (Di) ())
(defclass Di () ())
for 0 <= i < n.
The New Flavors algorithm, as described, seems to take n+1 passes, though
there is exactly one total order possible.
This is true. I'm not sure that it's significant. Does topological sort run
in linear time?
Given ... that there is no intuition to any order beyond what the
topological sort gives you ...
I agree with Danny's disagreement with this. I'm interested in continuing
the search for an algorithm that is acceptable to your algorithms wizard
and at the same time provides the intuitive behavior. It's getting late for
me, but I'll follow up on this tomorrow.
∂28-Jan-87 0713 DLW@ALDERAAN.SCRC.Symbolics.COM :allocation :none
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 28 Jan 87 07:13:38 PST
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 44181; Wed 28-Jan-87 10:12:23 EST
Date: Wed, 28 Jan 87 10:10 EST
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: :allocation :none
To: Moon@STONY-BROOK.SCRC.Symbolics.COM,
Common-Lisp-Object-System@sail.stanford.edu
cc: CLOS@STONY-BROOK.SCRC.Symbolics.COM
In-Reply-To: <870127230108.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870128101023.4.DLW@CHICOPEE.SCRC.Symbolics.COM>
Date: Tue, 27 Jan 87 23:01 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
In Flavors, we spent a lot of time some years ago discovering that that
style doesn't work very well. It worked out a lot better to split the
superclass into separate modules and then inherit whichever ones are
wanted.
I just read an interesting paper about programming style for object
oriented programming, written by Dan Halbert and <someone> from the
Trellis/Owl group at DEC's eastern research lab. It's based on their
experience teaching and helping users who were learning object-oriented
programming. It comes to the same conclusion, and strongly suggests
this kind of organization.
It was hard to figure out the implications of :allocation :none. One
example of a confusing case is where A inherits from B, B inherits from
C, C provides a slot S1, B declares S1 with :allocation :none, and A
declares S1 with :allocation :instance. One's "built-in" paradigms
about the concepts of "shadowing" and "inheritance from outer blocks"
and so on can easily lead to the impresion that A's S1 is distinct from
C's S1, whereas they are actually the same slot, and slot attributes are
inherited by A from C even though B "doesn't have" slot S1. It's also
confusing that instance of B "undermine" inherited methods from C that
refer to S1, by making S1 not be there any more.
I don't think this paradigm fits well into the overall proposal, and the
benefits of this feature seem relatively small compared to the extra
complexity and confusion that it adds to the specification. We've run
into such things before, many times, during this design process. I
suggest that we apply our usual treatment: remove this from the
specification per se, and leave it as a possible future feature, or
implemention-specific enhancement.
∂28-Jan-87 1005 RPG Complexity of Topological Sort + single-pass treewalk tiebreaker
To: common-lisp-object-system@SAIL.STANFORD.EDU
Let n be the number of classes at or above the one for which you which to
compute the CPL; let m be the sum of the number of direct superclasses at
each class at or above the class of interest. You can do the tiebreaker
treewalk in O(n) time; the topological sort O(n+m), so the whole thing is
linear.
-rpg-
∂28-Jan-87 1754 Bobrow.pa@Xerox.COM Re: Method Combination
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jan 87 17:48:23 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JAN 87 13:40:25 PST
Date: 28 Jan 87 13:40 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Method Combination
In-reply-to: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET's message of 27 Jan
87 17:39:46
To: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
cc: Bobrow.pa@Xerox.COM, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870128-134025-121@Xerox>
Date: 27 Jan 87 17:39:46
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
I agree with the fact than one can define ones own
compute-effective-method. The issue has to do with modularity.
Compute-effective-method has to find the list of all the method
that can be called, find the method combination method, call it to
come up with the code for the effective method. We need to keep
those operations as independent as possible. If we supply the
information as an argument to the method combinator, the user
writing a method combination method does not have to worry about
how the information was obtained.
I agree that finding the list of all the methods that can be called,
finding the way to combine methods, and coming up with the code for the
combination ought to be kept separate. The following describes my view
of the meta-object protocol, and how these are kept separate.
The meta-object protocol for building the code for generic functions
consists of two parts. The top level is
(compute-discriminator-code generic-function)
which has as its responsibility building the code that implements the
effect of the described four step protocol for calling a method. Its
usual implementation caches all the possibly different effective methods
for the generic-function, and it produces code to decide which of these
effective methods to call for any set of arguments. It is this code
that is run when the generic-function is called.
The only information compute-discriminator-code can use must be
contained in the generic-function object. THERE IS NO OTHER PLACE TO
STORE INFORMATION.
As a standard part of the protocol for compute-discriminator-code (which
can be overwritten by a specialized method), compute-discriminator-code
computes the set of applicable-methods for distinguishable sets of
arguments, and for that set calls:
(compute-effective-method generic-function combination-type
applicable-methods)
The combination-type is taken from the generic-function to allow
discrimination on an individual (the combination type) to select a
specialized method. Other paramaterized information could have been
passed in as arguments, but since that information is not being used for
discrimination, it might as well be left in the generic function.
Different implementations of compute-effective-method will be
able to call the same method combinator even if they use different
ways to come up with the method combination method. It seems more
modular and more general than extracting the information in the
method.
If you want a subfunction that combines method-lists in the same way for
differently named method-combination types (say because the lists are
computed in different ways), then by all means define a subfunction.
That was the reason we wanted make-method-call to be callable any place
the generic-function object was accessible.
Date: Wed, 28 Jan 87 00:05 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
I don't think the short form is vitally important, but until we
converge on all details of the long form it's difficult to tell how
much syntactic verboseness and error-proneness the short form will
save. I suggest that for right now a boldface note be added to the
document saying that the short form is still under discussion and
there is a good chance it will go away in a future revision.
I would rather do it the other way -- to make it easier to read the
document and to allow the need for a short form to emerge rather than
have it around by default. Only one form should appear in the document,
and prhaps we should have a footnote saying that we might consider a
short form if necessary.
I agree with Patrick's argument that storing parameters in the
generic function won't work.
I think I have answered Patrick above. If I have misunderstood the
thrust of the argument, please explain further.
I consider it important to design the lean standard so that
such extensions can be added smoothly and painlessly, without
making incompatible changes to the original standard. This means
that some design choices, which could go either way when considered
in isolation, need to go a certain way in order to leave room for
possible extensions. Is this agreeable to the other participants?
I agree with this in principle, and would want to see the argument in
any particular case.
This is the reason for the lambda-list. Having to say () now
is relatively painless, but adding a lambda-list in the future
would be difficult. In fact the lambda-list also turns out to be a
better way to provide access to the generic-function object than
any other I've thought of.
I've answered for the lack of need for the lambda-list above. The
lambda-list cannot just be (). In your examples, it was at least
(generic-function) or (generic-function order). This is not even the
complete lambda-list of compute-effective-method (it doesn't include
combination-type and applicable-methods).
I would be agreeable to removing the :order keyword if a lean
standard is paramount, although it seems to add only minimal
complexity and I've seen reversed order of method specificity used
quite a lot.
Most slightly shorter forms are used if they are available. But I
wouldn't cry a lot if this were put back.
I'm opposed to using optional arguments instead of keyword
arguments, because it makes extensibility much more awkward.
This is a case in which allowing for extensions seems to be the
paramount issue. Is it really musch easier to start with optionals and
then add keywords for extensions than to have all keywords. Not having
programmed with them very much, I can't speak from experience. I would
be happy to back off on this.
Using a special value for the :operator argument instead of a
:call-next-method argument would be okay with me, although I
suspect it will be difficult to document in a way that does not
cause confusion.
I think it will be less confusing for users to think of
:call-next-method as a special kind of operator. We seem to have no
real disagreement here. An argument for using the :call-next-method
instead of 'call-next-method (no colon) is to avoid people believing
that there is a function by that name, as there is for progn and and.
{method-combination-option} :=combination-keyword value
The list of method-combination options is optional, and is
distinguished from a form because it starts with a keyword.
We have this syntax for method-combination options in Flavors
and I think it is grotesque. I suggest not including this.
Can you say more about why you think it is grotesque. I find it easy to
spot and read.
The variable {\it generic-function\/} is available in
the body forms of the combination definition.
That's how we do it in Flavors (the variable name is slightly
different) and I think it is grotesque. It's usually better to let
the programmer choose her own names for variables. I suggest not
doing this, although I don't feel very strongly about it.
I think this is the simplest way to get access to the generic-function,
and if the programmer wants to use a name of her own, then she can
rebind it.
Question: How does make-method-call get access to the generic function.
I believed that it could assume access to that name in the lexical
scope. Or perhaps generic-function should be a dynamic variable, to
allow access for an error function.
(From Gregor) I like the new :around method-combination option.
I think
this will make it easier for people to deal with :around
methods. We might want to think about changing the "sense" of
this option, or changing the default, so that aroundification
happens by default.
(From Moon) I agree that once it's a yes/no option, it makes sense
to have
it turned on by default. The next logical step is to say that if
you want to turn it off, you should be operating at the meta-object
level. Do you ever feel like you're going around in circles? What
got us to :around methods in the first place was you guys' dislike
of Flavors whoppers, which cannot be turned off. (Obviously if
Flavors had meta-objects, whoppers could be turned off at the
meta-object level.)
Because around methods are still somewhat contentious (e.g. with
Fahlman) that I think :around should be explicit in the
define-method-combination code, and it should have to be turned on.
Standard method combination supports it without having to say something.
I understand the motivation for allowing a predicate
instead of the templates. I think that motivation should be
presented explicitly since without it, the predicate seems like
uneeded complexity.
I agree. Danny, could you write a paragraph about this? (Am I
remembering correctly that you invented the idea of putting the
predicate here?)
Yes I will. Yes I did.
We've found that it's often a good idea to provide a function
as an abstraction, even when all that function does is signal a
condition. The name of the condition can be the same as the name of
the function, so that there aren't any extra names to document.
This is what I had in mind here, rather than making a kludge to
cope with not having a standard condition system yet.
I suggest leaving this the way it is except for documenting the
rationale better.
I could go either way with this. If we have to document two kinds of
errors anyway, I guess it is as well to document functions.
I still don't like calling the default kind of method
combination standard. I would prefer if we called it default,
in fact, it might be better to call it daemon-with-around or
some other descriptive name.
I disagree. I really liked Danny's suggestion of calling it
standard. As you know, I think all the predefined objects that are
used by default if you don't make your own should be named
standard-xxx (standard-class, standard-method, etc.) I suggest
naming it either standard or standard-method-combination.
I still like "standard" since it is only used in a context that makes it
clear what it is the standard for.
One answer is for that library to be available, but not
necessary to be preloaded in all implementations. Then the
portable programmer can load it if it is not already loaded, but
doesn't have to reinvent it.
I suggest that the document should mention this issue but that
the name of and method combination in the example should still be
and.
I agree with both of these points. I think talking about standard
libraries here would be a good way of getting the point in the large,
without committing us to solve a problem.
My conclusion is that we should only have one define-method-combination
form in the document. The one still contentious issue between Moon's
and my ideas on this subject is the lambda-list. I hope this message
sheds more light on that issue. We should continue to try to reach
some consensus.
danny
∂28-Jan-87 1922 RPG Last-Visited Preorder
To: common-lisp-object-system@SAIL.STANFORD.EDU
If we decide the last-visited preorder is what we want for
a tiebreaker, then there is a simple linear way to compute it
without having to wonder whether reversed reversed postorder is
the same as last-visited preorder.
For every class you keep track of the in-degree with respect to the
sublattice of interest; the in-degree is the number of direct subclasses
of a class. When you walk from the class of interest, you keep track of
how many times you've visited that class. When you have visited it the
same number of times as its in-degree, you can walk from that class. The
exception is the class of interest, which you will visit once more than
its in-degree (you visit it once and its in-degree is 0).
-rpg-
∂28-Jan-87 1932 RPG Progress is Our Most Important Problem
To: common-lisp-object-system@SAIL.STANFORD.EDU
Wasn't that GE's slogan?
According to my calculations, we have 3 days left before the
document must be ready. I see a number of problems.
1. We are still arguing over CPL computation. When I asked Ken Olum
to tell me what he thought about the possible algorithms for it
he said he simply tried things in New Flavors until they worked.
He said a good model is that there is some sort of algorithm and you
don't try to understand it. Then he ran out of the room.
Now that I've beaten everyone's brains out on the issue, I think we
can happily settle on topological sort with last-visited preorder as
the tiebreaker.
2. I'm inclined to go with Moon's method combination for now, though
some of Danny's simplifications are attractive.
3. I don't care about the change-class protocol as long as it works.
4. I'd like to flush :allocation :dynamic and :allocation :none.
If people want :allocation :none, then the inheritance writeup
needs work. (Sonya?)
5. Gregor offered to supply examples. His examples didn't match the
current specification very well, and LGD sent them back for more
work. All of the functions and macros in the examples ought to be
defined in the specification.
I think we really have until Feb 14 to get this all done, but is there
some way I can add to your desires to work hard on this and get it done?
-rpg-
∂28-Jan-87 2216 Moon@STONY-BROOK.SCRC.Symbolics.COM Elaboration on the Non-intuitiveness of New Flavors Algorithm...
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Jan 87 22:13:02 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 56789; Thu 29-Jan-87 01:10:40 EST
Date: Thu, 29 Jan 87 01:10 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Elaboration on the Non-intuitiveness of New Flavors Algorithm...
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 27 Jan 87 21:01 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870129011004.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
I agree with your [Dick's] analysis of the behavior of the New Flavors
algorithm. This funny behavior when multiple passes are required is the
same thing that has been bothering me. The New Flavors algorithm produces
an "intuitive" result in many cases, but in this complex case it loses.
I think we are likely to support some variant of the Gabriel or Bobrow
proposed algorithms instead; so far the Bobrow one seems to produce the
most consistently intuitive results. I fixed its performance problem
that I mentioned yesterday by changing compute-must-precedes-closure;
in place of
(pushnew precede closure)
(walk precede (cons element path))
do
(unless (member precede closure)
(push precede closure)
(walk precede (cons element path)))
The case that I gave up on after waiting a minute takes 0.23 seconds
now, just about the same as the others (although Bobrow conses 3 times
as much). None of the algorithms I've been comparing have been coded
with speed paramount. I don't know whether the Bobrow algorithm is easy
to explain, though.
I also tried a variant of the Bobrow algorithm where the initial
elimination of duplicates preserves the first occurrence of each
class instead of the last. It's interesting but not really better.
I don't think any topological sort tie-breaker based on non-local
considerations such as preorder or postorder treewalk is going to
produce intuitive results in all cases, because intuition depends on
local considerations. I've been trying various tie-breakers but
no good results yet. The advantage of the Bobrow algorithm is that
it is preorder when that works, and when it doesn't, it moves things
the minimum distance required to make them work. It usually produces
the same result as the Gabriel-postorder algorithm, but
here is an example that shows that the last-visit disambiguation of
topological sort is not the same as the Bobrow-Kiczales algorithm.
(DEFCLASS A (B C D E F))
(DEFCLASS B (F X))
(DEFCLASS C (F Y))
(DEFCLASS D (F X))
(DEFCLASS E ())
(DEFCLASS F ())
(DEFCLASS X ())
(DEFCLASS Y ())
Flavors, Gabriel-pre, Bobrow produce A B C D E F X Y
Gabriel-post produces A B C D E F Y X
It's hard to say which is intuitive in this case, so I mention this
example only to show that Bobrow and Gabriel-post are not equivalent.
I want to continue thinking about a better tie-breaker for
topological sort.
∂29-Jan-87 0206 RPG CPL Tiebreaker
To: Common-Lisp-Object-system@SAIL.STANFORD.EDU
Ugh, bletch. I think I am really going to regret having written
this message. I think I found the tiebreaker. It passes all of
the hard intuitive cases, which I'll list below, along with all
of the cases ever mailed out.
The tiebreaker applies when there is more than one class with
no predecessors. The tiebreaker has two cases. The first case
is based on this reasoning by Danny (I'll paraphrase):
``If the user has a class and splits that class into two classes with no
other references to the direct superclass, there should be no chance of
any interaction with any other class used as a mixin. Hence one wants all
superclasses of a class to follow as soon as possible after the class they
are related to.''
This is very intuitive, and preorder treewalk is very intuitive. So
we do Danny's condition first and then preorder treewalk. Danny's
condition means this:
We define a relation called unique direct subclass. C is the unique direct
subclass of D if C is the only direct subclass of D. If class X was just
output and X is a unique direct subclass of some class D, D immediately
follows X. Otherwise, ties are broken by preorder treewalk (not
last-visited).
This means that we treat parts of the lattice that look like this:
\|/
D
|
C
/|\
as if they looked like this:
\|/
(D,C)
/|\
[Actually, the above picture is exactly how I looked when I discovered
this tiebreaker.]
Here are the hard cases:
(DEFCLASS A (B C D E F) ())
(DEFCLASS B (F X) ())
(DEFCLASS C (F Y) ())
(DEFCLASS D (F X) ())
(DEFCLASS E () ())
(DEFCLASS F () ())
(DEFCLASS X () ())
(DEFCLASS Y () ())
(topologically-sort 'a) = (A B C D E F X Y)
Well, this is simply preorder treewalk at work.
(DEFCLASS PTEST1 (PTEST2 PTEST3 PTEST5) ())
(DEFCLASS PTEST2 (PTEST5) ())
(DEFCLASS PTEST3 (PTEST4) ())
(DEFCLASS PTEST4 () ())
(DEFCLASS PTEST5 () ())
(topologically-sort 'ptest1) = (PTEST1 PTEST2 PTEST3 PTEST4 PTEST5)
In this one, PTEST3 is the unique direct subclass of PTEST4, so when
PTEST3 is output, PTEST4 and PTEST5 could come next. Preorder would
say PTEST5 is next, but Danny's rule overrides that.
(DEFCLASS PPTEST1 (PPTEST-MIXIN PPTEST2 PPTEST3) ())
(DEFCLASS PPTEST-MIXIN (PPTEST3) ())
(DEFCLASS PPTEST2 (PPTEST-INTERMEDIATE-1) ())
(DEFCLASS PPTEST3 (PPTEST-INTERMEDIATE-2) ())
(DEFCLASS PPTEST-INTERMEDIATE-1 (PPTEST-BASE) ())
(DEFCLASS PPTEST-INTERMEDIATE-2 (PPTEST-BASE) ())
(DEFCLASS PPTEST-BASE () ())
(topologically-sort 'pptest1)
= (PPTEST1 PPTEST-MIXIN PPTEST2 PPTEST-INTERMEDIATE-1 PPTEST3
PPTEST-INTERMEDIATE-2 PPTEST-BASE)
This one is nearly the same as the one before.
This addition condition adds no complexity to the algorithm, because
we compute the in-degrees of each class at DEFCLASS time.
-rpg-
∂29-Jan-87 0702 skeene@STONY-BROOK.SCRC.Symbolics.COM Progress is Our Most Important Problem
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Jan 87 07:01:48 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 56895; Thu 29-Jan-87 09:32:52 EST
Date: Thu, 29 Jan 87 09:32 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Progress is Our Most Important Problem
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 28 Jan 87 22:32 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870129093246.4.SKEENE@JUNCO.SCRC.Symbolics.COM>
Date: 28 Jan 87 1932 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Wasn't that GE's slogan?
According to my calculations, we have 3 days left before the
document must be ready. I see a number of problems.
1. We are still arguing over CPL computation. When I asked Ken Olum
to tell me what he thought about the possible algorithms for it
he said he simply tried things in New Flavors until they worked.
He said a good model is that there is some sort of algorithm and you
don't try to understand it. Then he ran out of the room.
Now that I've beaten everyone's brains out on the issue, I think we
can happily settle on topological sort with last-visited preorder as
the tiebreaker.
2. I'm inclined to go with Moon's method combination for now, though
some of Danny's simplifications are attractive.
I guess Danny and Gregor are really opposed to the short form of
DEFINE-METHOD-COMBINATION. Although I support the high-level goal
of keeping the standard lean, I disagree with this particular point.
The short form is easy to use, easy to document, and easy to understand.
It reduces the need for almost-duplication of code (when defining more
than one simple type of method combination). And most of the forms of
method combination that we've seen people need and use can be defined
that way.
3. I don't care about the change-class protocol as long as it works.
I'm adding this to the document right now.
4. I'd like to flush :allocation :dynamic and :allocation :none.
If people want :allocation :none, then the inheritance writeup
needs work. (Sonya?)
I've already rewritten the inheritance section according to suggestions
from Moon which you've seen, and comments from some people here. At
present, the document goes on the assumption that both :dynamic and
:none are still there.
I'd also like to flush them, though. I believe the consensus of our
in-house reviewers was the same. To me, :dynamic doesn't add anything
valuable to the programmer, and :none introduces a lot of complexity and
muddies up the model without adding much value.
I think we really have until Feb 14 to get this all done, but is there
some way I can add to your desires to work hard on this and get it done?
My personal desire to work hard on this and get it done is already
strong. I should be finished with adding the CHANGE-CLASS protocol and
moving some of the DEFINE-METHOD-COMBINATION writeup into the functions
chapter by today or tomorrow.
I agree with you that getting Problems 1, 2, and 4 settled as soon as
possible is the way to go. Number 3 isn't a problem, is it? I had the
impression that the mail reached consensus, and it's just a matter of
documenting it, which is almost done now anyway.
Why do you think we have until Feb 14?
-rpg-
I'd like to bring up one other point. Right now, only the Concepts and
Functions chapters have any real meat in them. I assume everyone
agrees that only those two chapters will be distributed in the March
meeting. The cover letter should mention that we will continue to work
on specifying the remainder of the Programmer Interface, and the
Meta-object Protocol.
∂29-Jan-87 1047 Bobrow.pa@Xerox.COM Re: Last-Visited Preorder
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Jan 87 10:47:36 PST
Received: from Salvador.ms by ArpaGateway.ms ; 29 JAN 87 09:46:31 PST
Date: 29 Jan 87 09:11 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Last-Visited Preorder
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 28 Jan 87
19:22 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870129-094631-1108@Xerox>
If we decide the last-visited preorder is what we want for a
tiebreaker, then there is a simple linear way to compute it without
having to wonder whether reversed reversed postorder is the same as
last-visited preorder.
For every class you keep track of the in-degree with respect to
the sublattice of interest; the in-degree is the number of direct
subclasses of a class. When you walk from the class of interest,
you keep track of how many times you've visited that class. When
you have visited it the same number of times as its in-degree, you
can walk from that class. The exception is the class of interest,
which you will visit once more than its in-degree (you visit it
once and its in-degree is 0).
There is a very simple double recursive program that does the same thing
without keeping track of in-degrees.
(DEFUN LAST-VISIT-ORDER (LAMBDA (C) (LV1 C NIL))
(DEFUN LV1 (C L)
(IF (MEMQ C L)
L
(LET ((S (DIRECT-SUPERS C)))
(PUSHNEW C
(IF (NULL S) L (LV2 S L)))))
(DEFUN LV2 (S L)
(LV1 (CAR S)
(IF (NULL (CDR S)) L (LV2 (CDR S) L))))
danny
∂29-Jan-87 1048 Bobrow.pa@Xerox.COM Re: Progress is Our Most Important Problem
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Jan 87 10:48:04 PST
Received: from Salvador.ms by ArpaGateway.ms ; 29 JAN 87 09:46:59 PST
Date: 29 Jan 87 09:38 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Progress is Our Most Important Problem
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 28 Jan 87
19:32 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870129-094659-1114@Xerox>
1. We are still arguing over CPL computation. When I asked Ken
Olum to tell me what he thought about the possible algorithms for
it he said he simply tried things in New Flavors until they worked.
He said a good model is that there is some sort of algorithm and
you don't try to understand it. Then he ran out of the room. Now
that I've beaten everyone's brains out on the issue, I think we can
happily settle on topological sort with last-visited preorder as
the tiebreaker.
The differences are now so small I don't care between B-K and this. I
think explainability is paramount. I think my algorithm is explainable
simply (e.g. as a local constraint satisfaction algorithm that modifies
last-visited tree walk). It does not refer to Knuth though, which has
status.
2. I'm inclined to go with Moon's method combination for now,
though some of Danny's simplifications are attractive.
I really don't want to see two define-method-combination forms. Do you
say this because you are tired and don't want to think (argue) through
the issues on this, or what? I would like to see Moon's comments on my
latest suggestions. As I said, the only real issue is the lambda-list.
I don't really care if we have documentation/declarations in the
defmacro way, and don't mind seeing as Moon proposed:
(1) Make it a method-group keyword option. Thus you say
((around (:around) :call-next-method t)
...other method groups...)
What happens if other method-groups have :call-next-method t
We could abbreviate the above as in.
((:around t) ... other method groups...)
thus assuring it can appear only once in the list, implicitly with
:around as the group specifier. It is really short, so users will
probably do it, and get it right. However this mixes syntax for
specifiers (ugh).
Let us argue through lambda-list, have a single
define-method-combination and I will edit the rest into the consensus.
3. I don't care about the change-class protocol as long as it
works.
We seem to have agreement here.
4. I'd like to flush :allocation :dynamic and :allocation
:none. If people want :allocation :none, then the inheritance
writeup needs work. (Sonya?)
I still think both are useful, but the one I have had lots of experience
with is :dynamic. I want to keep :dynamic that even if :none goes away.
danny
∂29-Jan-87 1402 skeene@STONY-BROOK.SCRC.Symbolics.COM changes made to documentation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Jan 87 13:58:29 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 57520; Thu 29-Jan-87 16:57:05 EST
Date: Thu, 29 Jan 87 16:57 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: changes made to documentation
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870129165700.9.SKEENE@JUNCO.SCRC.Symbolics.COM>
I just wrote new versions of the functions and concepts files.
The major changes I made include:
Concepts:
- Simplified "Defining a Class"
- Added section "Redefining a Class"
- Rewrote Inheritance of Slots
Functions:
- Fixed description of arguments to DOCUMENTATION
- Made the syntax of options in DEFCLASS stand out better in
the description of each option
- Fleshed out DEFINE-METHOD-COMBINATION to include a description
of each option. Note that these are just one-liners, and the
full syntax is still in the Concepts chapter, as are the examples.
I think this is the best way we can describe this function.
- Rewrote CHANGE-CLASS according to latest proposal
- Added description of CLASS-CHANGED
- Added several See Also fields. For example, you wanted to discuss
"compatibility
- Fleshed out the Introduction to mention what role each function and
macro plays -- that is, I put them into categories. This should
help people put the functions into a context. People at Symbolics
who read the drafts of this were put off by the alphabetic
(contextless) order of functions, so this should solve that
problem.
---------------
I also made the changes suggested in Moon's message.
∂29-Jan-87 1652 RPG The Real Deadline
To: common-lisp-object-system@SAIL.STANFORD.EDU
CC: mathis@A.ISI.EDU
In order to get the documents out in time for people to prepare for the
Palo Alto meeting, I have set the following hard, non-negotiable
deadlines:
1. The last technical changes have to be done to both
files (CONCEPTS and FUNCTIONS) by midnight, Sunday
February 8. At that point I am putting the documents
into my technical writing staff maw to check for
blatant problems.
2. I will federal express the final documents to Bob Mathis
on Friday, February 13.
3. I think this means that Sonya can have the files until
Monday, February 2.
I think that unless there is a draft of the metaobject stuff by Friday,
February 6, we must decide how to proceed - I see the most likely option
being to flush metaobjects altogether until a later date.
In Gregor's examples there were several functions used that are not
specified. I suggest people search their expectations of what should be
there and compare them to what actually is there, because on February 9
they cannot be added in this draft - we will look very silly, indeed.
-rpg-
∂29-Jan-87 1708 "Patrick H Dussud %Jenner%ti-csl.csnet"@RELAY.CS.NET Re: Method Combination
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Jan 87 17:07:10 PST
Received: from ti-csl by csnet-relay.csnet id ab02015; 29 Jan 87 19:18 EST
Received: from dsg (juliett.ARPA) by tilde id AA13743; Thu, 29 Jan 87 17:04:44 cst
Received: FROM Jenner BY dsg Via CHAOS-NET with CHAOS-MAIL; 29-Jan-87 16:52:31
Message-Id: <2747948035-1026455@Jenner>
Sender: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Date: 29-Jan-87 16:53:55
From: "Patrick H Dussud %Jenner%ti-csl.csnet"@RELAY.CS.NET
To: Danny Bobrow <Bobrow.pa@XEROX.COM>
Cc: common-lisp-object-system@SU-AI.ARPA,
DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Subject: Re: Method Combination
In-Reply-To: In-Reply-To: Msg of 28-Jan-87 15:40:00 from Danny Bobrow <Bobrow.pa@xerox.com>Msg of 28-Jan-87 15
Date: 28-Jan-87 15:40:00
From: Danny Bobrow <Bobrow.pa@xerox.com>
Date: 27 Jan 87 17:39:46
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
I agree with the fact than one can define ones own
compute-effective-method. The issue has to do with modularity.
Compute-effective-method has to find the list of all the method
that can be called, find the method combination method, call it to
come up with the code for the effective method. We need to keep
those operations as independent as possible. If we supply the
information as an argument to the method combinator, the user
writing a method combination method does not have to worry about
how the information was obtained.
I agree that finding the list of all the methods that can be called,
finding the way to combine methods, and coming up with the code for the
combination ought to be kept separate. The following describes my view
of the meta-object protocol, and how these are kept separate.
The meta-object protocol for building the code for generic functions
consists of two parts. The top level is
(compute-discriminator-code generic-function)
which has as its responsibility building the code that implements the
effect of the described four step protocol for calling a method. Its
usual implementation caches all the possibly different effective methods
for the generic-function, and it produces code to decide which of these
effective methods to call for any set of arguments. It is this code
that is run when the generic-function is called.
The only information compute-discriminator-code can use must be
contained in the generic-function object. THERE IS NO OTHER PLACE TO
STORE INFORMATION.
I don't have problem with this, the problem is how you access it. (See
below).
As a standard part of the protocol for compute-discriminator-code (which
can be overwritten by a specialized method), compute-discriminator-code
computes the set of applicable-methods for distinguishable sets of
arguments, and for that set calls:
(compute-effective-method generic-function combination-type
applicable-methods)
The combination-type is taken from the generic-function to allow
discrimination on an individual (the combination type) to select a
specialized method. Other paramaterized information could have been
passed in as arguments, but since that information is not being used for
discrimination, it might as well be left in the generic function.
Ah, this is interesting. The combination type is "taken" from the generic
function by compute-effective-method, which might need the sets of
arguments you talked about earlier. But then, if you don't pass somehow
(arguments, special variable .....) all the information relevant to this
combination type, then the user has to "take" it again from the
define-combined-method code. This is not the business of the method
combination method to know how to "take" it from the generic
function. If you wonder why we would have to use the set of arguments to
compute the method combination type, you can (re)read my mail about
method combination selection that David mentioned in his last message.
I don't have time to comment on the rest of the message today. I'll hold
off until you have something more concrete on the metaclass protocol
since this is what it is all about.
Patrick.
∂29-Jan-87 1713 Gregor.pa@Xerox.COM Re: Progress is Our Most Important Problem -- Method
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Jan 87 17:09:24 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 29 JAN 87 15:59:40 PST
Date: 29 Jan 87 15:59 PST
From: Gregor.pa@Xerox.COM
Subject: Re: Progress is Our Most Important Problem -- Method
Combination
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 28 Jan 87
19:32 PST
To: RPG@SAIL.STANFORD.EDU
cc: Bobrow.pa@Xerox.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870129-155940-1249@Xerox>
As for all this fuss about method combination,
I have to ask, what do you suppose will be the ratio of
define-method-combinations to defmethods in Common Lisp code?
1/1000?
1/10000?
1/100000?
Because actual define-method-combination forms are so rare, but
interaction with method combination is so common, I think the most
important thing about method combination is the abstraction. People
need to be able to understand how method combination works a lot more
often than they need to be able to type a define-method-combination. I
think that a lot of progress has been made in improving the abstraction,
and I think thats real good.
I believe that both define-method-combination proposals on the table are
terribly over-engineered. They have convenience mechanisms and bells
and whistles that are not appropriate for such a rarely used form.
Including two different versions of define-method-combination is an
excellent example of this kind of over-engineering.
Because of these beliefs, I prefer Danny's proposal to Moon's just
because it is simpler.
∂29-Jan-87 1722 RPG Re: Algorithms
∂29-Jan-87 1713 Bobrow.pa@Xerox.COM Re: Algorithms
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Jan 87 17:09:13 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 29 JAN 87 15:38:48 PST
Date: 29 Jan 87 15:38 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Algorithms
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 29 Jan 87
13:44 PST
To: RPG@SAIL.STANFORD.EDU
cc: bobrow.pa@Xerox.COM
Message-ID: <870129-153848-1220@Xerox>
The sort of algorithms I look for are the sort that don't cons
at all. Your algorithm with its MEMQ probably bloats to n↑2 at some
point (or worse). In my algorithms you keep track of something one
of whose parts is in-degree, which you keep track of at DEFCLASS
time.
The algorithm I gave conses exactly once for each class in the list.
The in-degree of a class is not the same for each subclass. Hence you
must keep some information per class in the eventual tree walk. How do
you do that. If you don't like MEMQ, then you can keep a separate
hashtable that is a linear test for already occurred. But the number of
classes, and hence the number n is small as is the constant.
But I am clearly not understanding your algorithm if I think the
in-degree is class dependent. Can I see the code please?
danny
∂29-Jan-87 1713 Gregor.pa@Xerox.COM My comments on some things
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Jan 87 17:08:57 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 29 JAN 87 15:12:41 PST
Date: 29 Jan 87 15:12 PST
From: Gregor.pa@Xerox.COM
Subject: My comments on some things
To: Common-Lisp-Object-System@Sail.Stanford.edu
cc: Gregor.pa@Xerox.COM
Message-ID: <870129-151241-1183@Xerox>
I am amenable to making methods not be funcallable in the way that
generic-functions are. Let me take this opportunity to repeat that I am
not amenable to allowing the method function of a method not be
FUNCALLable with the "natural" arguments. I am fairly certain Danny
agrees with me on this issue. I think this is something we need to talk
about the next time we get together. I believe that we can show
"meta-objecty" programs which may it clear what a pain this would be.
---
I believe the simplest way to rephrase the much maligned (and
deservedly) phrase "the classes at or above C" is "C and all of its
superclasses", or perhaps just "C and its superclasses".
---
What does the phrase "x is of class array mean"? In the first paragraph
of the section Integrating Types and Classes in Concepts (draft of 1/23)
it is used to mean "x is of class array or some subclass of array"? Is
that official?
--
Args to get-method and make-instance of 'method
More along the lines of names not being the same ast the "objects they
name", I would like to change get-method and the specializers of a
method to be either (QUOTE <datum>) or a class OBJECT. That means that
instead of saying:
(get-method #'print-object () '(symbol t))
you would say:
(get-method #'print-object () (list (class-named 'symbol)
(class-named 't)))
or use mapcar or something.
Admitedly this is somewhat longer, but I believe it is clearer, it keeps
to the abstraction that "names are supported by things which start with
DEF", but below that level of abstraction we deal with class and generic
function objects. This allows programming with anonymous classes and
generic functions to be clean since names are not tied in at the
low-level of the system.
---
Slot inheritance rules.
Here is my proposal for slot inheritance rules. It isn't in english, it
more of a FSM, but I believe its clear, and if we all agree then it can
be put in english.
First, what are the default values for the various slot options:
:initform defaults to unsupplied, what this means exactly will become
clear
:type defaults to T
:allocation defaults to :instance
Now, how are the slot descriptions from all the different defclasses
where a slot of a particular name appears merged.
First, get the slot descriptions in class-precedence-list order.
Then, merge the individual options as follows.
:initform, take the most specific :initform which is supplied, or take
unsupplied if :initform is not specified in any of the slot
descriptions
:type The total type is and of all the types specified.
:allocation the allocation of the most specific slot.
Note that this rule, means that you can't change the
default value of a :class variable which you inherited,
this is a feature, not a bug, it makes the rules simpler
too.
Some examples:
(defclass foo () ((a :initform 1)))
(defclass bar (foo) ((a :initform 2 :type integer)))
(defclass baz (bar) ((a :initform 3)))
BAZ's effective description for A is:
(A :initform 3 :type (and t integer t) :allocation :instance)
(defclass foo () ((a :initform 'george))
(defclass bar (foo) ((a :type symbol)))
BAR's effective description for A is:
(A :initform 'george :type (and t symbol) :allocation :instance)
(defclass foo () ((a :allocation :class :initform ()))
(defclass bar (foo) ((a :initform *a-default*)))
BAR's effective description for A is:
(A :initform *a-default* :type (and t t) :allocation :instance)
Note that instances of FOO have access to a class variable of the class
FOO named A.
Instance of BAR each have their own variable named A.
---
In introduction to generic functions, (also concepts of 1/23), the
paragraph (with a bullet) which reads:
Generic functions are named precisely as ordinary functions. When a
generic
functions is associated with a symbol, that name is in a certain
package and
can be exported...
just confuses the issue. The point is that (unfortunately) packages
talke about symbols, not definitions or bindings. Symbols can always be
exported. I think the point you are really try to make is just that
- generic functions are function objects,
- the same rules apply as to all other function objects,
- as with other function objects, they are often stored in the function
cell of a symbol (with defmethod etc.),
∂29-Jan-87 1713 Gregor.pa@Xerox.COM Re: symbols are not generic functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Jan 87 17:09:35 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 29 JAN 87 16:05:48 PST
Date: 29 Jan 87 16:05 PST
From: Gregor.pa@Xerox.COM
Subject: Re: symbols are not generic functions
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 27 Jan 87 23:05 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870129-160548-1259@Xerox>
in reference to ensure-generic-function, Moon says:
I don't completely understand. Suppose symbol-function of the
symbol
is already a generic function, but it is of a different class than
the
kind that you get by default, because someone is using
generic-function
meta-objects. Would ensure-generic-function accept that generic
function, signal an error, or clobber it with a generic function of
the default kind?
Well, the short lazy answer is ensure-generic-function does whatever
add-method was going to do.
The long answer is we need to figure this out.
1. perhaps ensure-generic-function should take a second argument which
would be the class of the generic function to make if there isn't one.
2. There is a part of the meta-object protocol which deals with whether
or not is is permissible to change the class of a generic function, that
part of the protocol should be called here when there is already a
generic function but its the wrong class.
3. Perhaps ensure-generic-function should take another argument which
could be used to specify that if there is a function in the place, but
its not a generic-function, it should become the default method for the
new generic function.
Also, does ensure-generic-function ever alter the symbol-function of
a symbol, or is it just a side-effect free coercion? If the latter,
it might be cleaner to use the existing COERCE function, thus
(add-method (coerce <arg> 'generic-function) <method>).
I am not sure about this given what I said above.
∂29-Jan-87 1930 Moon@STONY-BROOK.SCRC.Symbolics.COM CPL Tiebreaker
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Jan 87 19:29:37 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 57970; Thu 29-Jan-87 22:19:56 EST
Date: Thu, 29 Jan 87 22:19 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: CPL Tiebreaker
To: Common-Lisp-Object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 29 Jan 87 05:06 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870129221938.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 29 Jan 87 0206 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
I think I found the tiebreaker....
....is based on this reasoning by Danny (I'll paraphrase):
``If the user has a class and splits that class into two classes with no
other references to the direct superclass, there should be no chance of
any interaction with any other class used as a mixin. Hence one wants all
superclasses of a class to follow as soon as possible after the class they
are related to.''
I agree.
This is very intuitive, and preorder treewalk is very intuitive. So
we do Danny's condition first and then preorder treewalk.
Danny's condition means this:
We define a relation called unique direct subclass. C is the unique direct
subclass of D if C is the only direct subclass of D. If class X was just
output and X is a unique direct subclass of some class D, D immediately
follows X. Otherwise, ties are broken by preorder treewalk (not
last-visited).
I don't think this really makes it, although it comes quite close and has
very much the character of what I've been looking for. One problem is that
a class with two direct subclasses shouldn't really be treated completely
differently from a class with one direct subclass. A worse problem is
multiple superclasses: a single class X can have two direct superclasses Y
and Z, where X is a unique direct subclass of both Y and Z. Y and Z can't
both go immediately after X, and furthermore when you put in Y you can get
direct superclasses of Y, which must go either before or after Z. When I
tried this algorithm it soon foundered on those problems, but it did
stimulate me to think of another algorithm:
When topological sort finds multiple candidates to go in next, choose the
candidate that has a direct subclass rightmost in the class precedence list
computed so far. If that subclass has more than one direct superclass
among the candidates, take the superclass that is most specific according
to the subclass's local precedence order. In more technical language,
let {N1,...,Nm} be the candidates to go in next and {C1,...,Cn} be the
class precedence list constructed so far; C1 is the starting class and
is most specific, Cn is least specific. m>=2, n>=1. For i from n down
to 1, let {S1,...,Sk} be the direct superclasses of Ci, k>=1, then for
j from 1 up to k, if Sj is an element of {N1,...,Nm}, set Cn+1 = Sj and
proceed with the topological sort.
This algorithm does a good job of keeping related classes together. I like
this algorithm and I think we should adopt it. I added the above
paragraph to the document version that Sonya just finished editing;
it's on SU-AI now and we will be proofreading it tomorrow.
My trial implementation of this algorithm is extremely stupid, involving
three nested loops and no optimization whatever, yet is not perceptibly
slower than any of the others I've been trying, which surprised me. I'm
sure an algorithm wizard could write it much better.
I've tried this against all the flavors that happened to be defined in my
machine and it produces the same result except in the cases where the
flavors algorithm is broken. I plan to try it on some other Flavors
programs later. In the relatively simple cases (such as the ones I deleted
out of the message I'm replying to) this produces the same answer as the
previous Gabriel algorithm and the Bobrow algorithm.
∂29-Jan-87 2003 Moon@STONY-BROOK.SCRC.Symbolics.COM Gregor's comments on some things
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Jan 87 20:00:25 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 58015; Thu 29-Jan-87 22:59:23 EST
Date: Thu, 29 Jan 87 22:58 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Gregor's comments on some things
To: Common-Lisp-Object-System@Sail.Stanford.edu
In-Reply-To: <870129-151241-1183@Xerox>
Message-ID: <870129225845.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 29 Jan 87 15:12 PST
From: Gregor.pa@Xerox.COM
I am amenable to making methods not be funcallable in the way that
generic-functions are.
OK.
Let me take this opportunity to repeat that I am
not amenable to allowing the method function of a method not be
FUNCALLable with the "natural" arguments. I am fairly certain Danny
agrees with me on this issue. I think this is something we need to talk
about the next time we get together. I believe that we can show
"meta-objecty" programs which may it clear what a pain this would be.
Let's plan to talk about this in person, then.
---
I believe the simplest way to rephrase the much maligned (and
deservedly) phrase "the classes at or above C" is "C and all of its
superclasses", or perhaps just "C and its superclasses".
That's a good idea. I put it into the document, since I was editing
that part.
---
What does the phrase "x is of class array mean"? In the first paragraph
of the section Integrating Types and Classes in Concepts (draft of 1/23)
it is used to mean "x is of class array or some subclass of array"? Is
that official?
I think so. I believe "X is of class Y" and "X is an instance of Y" mean
that (class-of X) is Y or a subclass of Y, rather than (eq (class-of X) Y).
--
Args to get-method and make-instance of 'method
More along the lines of names not being the same ast the "objects they
name", I would like to change get-method and the specializers of a
method to be either (QUOTE <datum>) or a class OBJECT. That means that
instead of saying:
(get-method #'print-object () '(symbol t))
you would say:
(get-method #'print-object () (list (class-named 'symbol)
(class-named 't)))
or use mapcar or something.
Admitedly this is somewhat longer, but I believe it is clearer, it keeps
to the abstraction that "names are supported by things which start with
DEF", but below that level of abstraction we deal with class and generic
function objects. This allows programming with anonymous classes and
generic functions to be clean since names are not tied in at the
low-level of the system.
Well, it's pretty weird that symbols are turned into class objects but
QUOTE-expressions are not. This doesn't generalize very well to the
extension to supporting other Common Lisp type specifiers. Otherwise
I have no objection to the proposal, so if you can supply a brief design
rationale for doing it that way to go into the document I'm amenable.
Of course it makes get-method and related functions useless until we put
in the supporting functions such as class-named. Is there any reason
that these aren't documented already? That is, are there any
outstanding issues on these, or is it only a matter of writing the
information down and putting TEX commands into it? Do you Gregor, or
anyone else, have a list of these missing functions? I'm not talking
about the full meta-object protocol, just the functions needed to program
at the next level of abstraction below the defxxx macros.
---
Here is my proposal for slot inheritance rules....
I think this is the same as what Sonya and I worked out in the latest
version of the document. When you get that document, please read the
slot inheritance description and see if you think it says what you
want and is clear. If you have trouble retrieving the document from
SU-AI we can mail you the TEX source of that part.
---
In introduction to generic functions, (also concepts of 1/23), the
paragraph (with a bullet) which reads:
Generic functions are named precisely as ordinary functions. When a
generic
functions is associated with a symbol, that name is in a certain
package and
can be exported...
just confuses the issue. The point is that (unfortunately) packages
talke about symbols, not definitions or bindings. Symbols can always be
exported. I think the point you are really try to make is just that
- generic functions are function objects,
- the same rules apply as to all other function objects,
- as with other function objects, they are often stored in the function
cell of a symbol (with defmethod etc.),
I think this is the same as what Sonya and I worked out in the latest
version of the document. Maybe your bulleted list is a clearer way of
saying it though; we'll check on this.
∂29-Jan-87 2154 Moon@STONY-BROOK.SCRC.Symbolics.COM Minor things noticed while proofreading documents
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Jan 87 21:51:28 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 58055; Fri 30-Jan-87 00:50:30 EST
Date: Fri, 30 Jan 87 00:50 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Minor things noticed while proofreading documents
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870130005009.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
slot-spec syntax: did (slot-name initform) as a convenient abbreviation
for (slot-name :initform initform) go away accidentally, or did we
really decide to get rid of it? I don't remember discussing this.
:accessor-prefix, :reader-prefix: the document says that the argument to
these can be a string, a symbol, or nil. My memory is that we got rid
of the string and nil cases. True or false?
The documentation for get-method says that the specializers argument
is a list of parameter specializers. I proposed an alist format instead,
to allow extensibility to specializing on keyword arguments in the future.
I thought it was accepted. Was it rejected, or did the document just
not get updated yet? This applies to make-method also.
Should make-generic-function and make-method be flushed in favor of
documenting particular sets of arguments to make-instance that perform
those functions?
∂30-Jan-87 2218 RPG CPL etc
To: common-lisp-object-system@SAIL.STANFORD.EDU
After a day of meetings I was finally able to get back to our favorite
topic. Moon's tiebreaker variant admits a linear implementation, which is
pretty good. I have some questions about whether we think it is intuitive:
(defclass c1 (top) ())
(defclass c2 (top) ())
(defclass c3 (top) ())
(defclass d1 (c1 c2) ())
(defclass d2 (c1 c3) ())
(defclass e1 (d1 d2) ())
At some point Danny mentioned that the ``right'' order for this is
(E1 D1 D2 C1 C2 C3 TOP)
The new algorithm (and New Flavors, I think) produces
(E1 D1 D2 C1 C3 C2 TOP)
Is this less intuitive? More later.
Some people might have been confused by Moon's description. It read:
``When topological sort finds multiple candidates to go in next, choose the
candidate that has a direct subclass rightmost in the class precedence list
computed so far. ***If that subclass has more than one direct superclass
among the candidates, take the superclass that is most specific according
to the subclass's local precedence order.***''
The condition described in the sentence between the asterisks cannot
happen, so you shouldn't try to understand it. A candidate for
entering the final CPL has no predecessors, which means that all of its
siblings to the left have already been placed in the CPL, and so none of
them can be candidates to go next.
I think that in worrying about the CPL we have to keep in mind that most
people will operate under the following model: The direct superclasses
mentioned in the DEFCLASS form and their relative order are important. The
system will then provide some arbitrary total order, and the program will
have to be massaged until it works - simply because no one can understand
the algorithm. This is the model that KDO will have; KDO is no wimp.
Many people will wish they can simply supply their own ordering algorithm.
Here is a simple example, which many of you have seen before. There are 4
classes, perhaps poorly chosen:
Animate-things
blush-method = turn-pink
noseup-method = become-haughty
|
|
/ \
/ \
/ \
Turtles Green-animals
noseup-method = pick-up-pen blush-method = turn-purple
\ /
\ /
\ /
|
|
Green-turtles
Animate-things has two methods, blush-method and noseup-method. The effect of
the blush-method is to change colors and the effect of the noseup-method is
to change the attitude of the object to haughtiness. The first subclass is
Turtles, like LOGO turtles. The noseup-method shadows the animate-things method,
and the effect of it is to pick up the pen; the blush-method is ok. The second
subclass is Green-animals, and the blush-method is different, because when
a green thing turns pink, it really turns purple.
The final class is Green-turtles. This might be a dumb thing to do, but
the user's intuition might be reasonable. He sees that the Turtle noseup-method
is good, and that the Green-animals blush method is good, so he inherits from
both. But he has to mention Turtles and Green-animals in some order. If he
mentions them in the above order, he gets the wrong blush-method; if he reverses
them he gets the wrong noseup-method.
The solution is to reformulate the classes into more parts with hairy
relationships. A similar problem can happen when a user wants to inherit
slots. One can imagine an asymptotic situation where each DEFCLASS has
exactly one slot and you build your classes by the shopping cart method.
The user of the above class lattice believes that the CPL will reflect a
breadth-first CPL. The depth-first nature of all CPL computations so far
reflects a desire for ``transparency'' of subclass-superclass inheritance.
Perhaps we need to have a notation for inheriting from a set of
superclasses in no partocular order, which would signal the CPL
computation to go breadth-first. Maybe another partial solution is some
means of having generic functions be able to distinguish instances of
``this very class'' rather than instances of this very class or of its
subclasses.
In any event, what we are doing by defining the CPL computation as we
are is to provide a mechanism for people to curse the standard. Perhaps
it is necessary to have such a well-defined default, but maybe we should think
about a variety of alternatives from which the user can select as well
as an alternative to roll your own.
-rpg-
∂31-Jan-87 0923 RPG Common Lisp Types
To: common-lisp-object-system@SAIL.STANFORD.EDU
I bring up once more the question of classes for Common Lisp types.
In particular, the current Design Rationale chapter says there are
no classes for these things:
`` - Types too specific to be useful to put methods on: bit, keyword,
standard-char, string-char
- The type implies an implementation, not behavior: bignum,
fixnum, simple-array, simple-bit-vector, simple-string,
simple-vector
- Specification of the type is too vague: common, function, stream
- This is the same as (not cons), and we are not yet dealing with
not: atom
- No object can be an instance of this type: nil''
I propose that we not judge what is too specific to be useful to put methods
on. I can imagine system programmers thinking standard-char and string-char
are reasonable. I think implementation as a distinguishing characteristic
for a class is perfectly reasonable. I think we must try to treat functions
well, and that streams are necessary. I agree that NOT classes should not
be included.
So I propose that every implementation be required to provide the classes
explicitly excluded in the design rationale except for negation classes
(atom) and Common, though there may be no instances of them, and I presume
we can arrange for the metaclass to state that fact. Furthermore, I
propose that the structure of the lattice in the vicinity of
implementation-dependent types be variable, reflecting the implementation
hierarchy. For example, if an implementation has single-floats only, the
classes would be:
(defclass short-float (single-float))
(defclass long-float (single-float))
(defclass double-float (single-float))
(defclass single-float (float))
and only single-float would have instances. The other permissible
float configurations have different topology.
For functions, I propose that the Class Function include as instances
those objects in the Lisp that are in the range of the function Function.
For many implementations this will coincide with Compiled-Function, which
would be a subclass of Function. This means that CLOS adopts the attitude
that symbols and lists that happen to represent functions are the second-class
version of functions.
I propose that the class named NIL be at the bottom of the lattice and that
it also has no instances.
-rpg-
∂31-Jan-87 1156 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: symbols are not generic functions
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 31 Jan 87 11:53:11 PST
Received: from ti-csl by csnet-relay.csnet id ak20454; 31 Jan 87 14:16 EST
Received: from dsg (juliett.ARPA) by tilde id AA16277; Fri, 30 Jan 87 14:06:06 cst
Received: FROM Jenner BY dsg Via CHAOS-NET with CHAOS-MAIL; 30-Jan-87 14:05:34
Message-Id: <2748013225-902979@Jenner>
Date: 30-Jan-87 11:00:25
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
To: Gregor.pa@XEROX.COM
Cc: Common-Lisp-Object-System@SU-AI.ARPA
Subject: Re: symbols are not generic functions
In-Reply-To: In-Reply-To: Msg of 29-Jan-87 19:13:00 from System Files <SYS@su-ai.arpa>Msg of 29-Jan-87 19
in reference to ensure-generic-function, Moon says:
I don't completely understand. Suppose symbol-function of the
symbol
is already a generic function, but it is of a different class than
the
kind that you get by default, because someone is using
generic-function
meta-objects. Would ensure-generic-function accept that generic
function, signal an error, or clobber it with a generic function of
the default kind?
Well, the short lazy answer is ensure-generic-function does whatever
add-method was going to do.
This function is giong to be used for get-method and remove-method, its
behavior needs to be different for those because if there is no generic
function fbound to the symbol, we can't create one.
The long answer is we need to figure this out.
1. perhaps ensure-generic-function should take a second argument which
would be the class of the generic function to make if there isn't one.
2. There is a part of the meta-object protocol which deals with whether
or not is is permissible to change the class of a generic function, that
part of the protocol should be called here when there is already a
generic function but its the wrong class.
I agree
3. Perhaps ensure-generic-function should take another argument which
could be used to specify that if there is a function in the place, but
its not a generic-function, it should become the default method for the
new generic function.
Also, does ensure-generic-function ever alter the symbol-function of
a symbol, or is it just a side-effect free coercion? If the latter,
it might be cleaner to use the existing COERCE function, thus
(add-method (coerce <arg> 'generic-function) <method>).
I am not sure about this given what I said above.
I think this is a summary of what we can encounter:
Fboundp = nil: (error)
| (fdefine symbol (make-instance desired-type))
| (make-instance desired-type)
= t:
generic-function-p = nil: (error)
| (replace-without-default
(make-instance desired-type))
|(make-instance desired-type)
| (replace-with-default
(make-instance desired-type))
|(add-method
(make-instance desired-type)
.... old-function)
= t: (subtypep generic-function-type
desired-type) = t: generic-function
= nil: (error)
|(change-class)
|(make-instance desired-type)
To cover all the cases, we could have an arglist like this:
ensure-generic-function function-name &optional generic-function-type
&key :error-if-not-fboundp
:error-if-not-generic
:error-if-not-subtypep
:side-effect-p
If side-effect-p is nil, the old function-object is not changed and left
in the symbol-function slot of the symbol.
If side-effect-p is true, the old function-object is changed. If one has
to be created, it is put in the symbol-function of the symbol.
It would be useful for the function to return a second values to tell if
the symbol-function was returned, changed or if a new generic-function
was created. (Like INTERN).
Patrick.
∂31-Jan-87 2054 Moon@STONY-BROOK.SCRC.Symbolics.COM Moon/Bobrow phone conversation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 31 Jan 87 20:54:00 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 59286; Sat 31-Jan-87 23:52:44 EST
Date: Sat, 31 Jan 87 23:52 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Moon/Bobrow phone conversation
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870131235241.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
I made some changes to define-method-combination that Danny Bobrow and I
discussed on the phone. The generic-function is no longer in the lambda
list, instead it's a wired-in variable name. The lambda-list is still
present for expansion, but is () in standard method combination. The
short form is described after the long form and the expansion into the
long form is shown. compute-effective-method takes 4 arguments.
:operator :call-next-method replaces :around t in make-method-call.
The short form takes the operator as a keyword argument instead of a
positional argument. I think we all agree on this compromise now.
I didn't change :allocation :dynamic and :none. They're still in there,
but not explained very well.
∂31-Jan-87 2127 Moon@STONY-BROOK.SCRC.Symbolics.COM CPL etc
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 31 Jan 87 21:26:44 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 59293; Sun 1-Feb-87 00:10:40 EST
Date: Sun, 1 Feb 87 00:10 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: CPL etc
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 31 Jan 87 01:18 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870201001041.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 30 Jan 87 2218 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
....I have some questions about whether we think it is intuitive:
(defclass c1 (top) ())
(defclass c2 (top) ())
(defclass c3 (top) ())
(defclass d1 (c1 c2) ())
(defclass d2 (c1 c3) ())
(defclass e1 (d1 d2) ())
At some point Danny mentioned that the ``right'' order for this is
(E1 D1 D2 C1 C2 C3 TOP)
The new algorithm (and New Flavors, I think) produces
(E1 D1 D2 C1 C3 C2 TOP)
There's no way to avoid breaking up the superclasses of either D1 or D2,
so no order is going to be intuitive by Danny's rule of not breaking up
superclasses (equivalently, hiding the implementation of a component class
as a single class or a tree of superclasses). The new algorithm keeps D2
together and breaks up D1. The previous order breaks them both up. Not
much difference in my opinion.
Some people might have been confused by Moon's description. It read:
``When topological sort finds multiple candidates to go in next, choose the
candidate that has a direct subclass rightmost in the class precedence list
computed so far. ***If that subclass has more than one direct superclass
among the candidates, take the superclass that is most specific according
to the subclass's local precedence order.***''
The condition described in the sentence between the asterisks cannot
happen, so you shouldn't try to understand it.
Oh, right, this only happens if you add the extension that the local
precedence order of a class can be a partial order rather than a total
order. We have that in Flavors, and it comes in handy, but I'm not
proposing to standardize on it at this time.
I think that in worrying about the CPL we have to keep in mind that most
people will operate under the following model: The direct superclasses
mentioned in the DEFCLASS form and their relative order are important. The
system will then provide some arbitrary total order, and the program will
have to be massaged until it works - simply because no one can understand
the algorithm. This is the model that KDO will have; KDO is no wimp.
KDO is certainly not a wimp, but he is known for massaging things until they
work instead of understanding them.
Here is a simple example, which many of you have seen before....
....the user's intuition might be reasonable. He sees that the Turtle noseup-method
is good, and that the Green-animals blush method is good, so he inherits from
both. But he has to mention Turtles and Green-animals in some order. If he
mentions them in the above order, he gets the wrong blush-method; if he reverses
them he gets the wrong noseup-method.
I think you're mistaken. Animate-things is less specific than both
turtles and green-animals, in your diagram, so there is no danger of
getting the wrong method. In fact the order of the direct superclasses
turtles and green-animals doesn't affect the applicable methods at all.
In any event, what we are doing by defining the CPL computation as we
are is to provide a mechanism for people to curse the standard.
Is this based on the above mistaken example, or on other considerations?
∂01-Feb-87 1410 RPG CPL Varia
To: common-lisp-object-system@SAIL.STANFORD.EDU
Given that Moon has agreed that the example
(defclass c1 (top) ())
(defclass c2 (top) ())
(defclass c3 (top) ())
(defclass d1 (c1 c2) ())
(defclass d2 (c1 c3) ())
(defclass e1 (d1 d2) ())
producing the CPL (E1 D1 D2 C1 C3 C2 TOP) is ok, I am willing to
accept it. I will make sure the writeup is reasonable.
Moon's writes:
``Oh, right, this only happens if you add the extension that the local
precedence order of a class can be a partial order rather than a total
order. We have that in Flavors, and it comes in handy, but I'm not
proposing to standardize on it at this time.''
I'm not sure what this means, but whether the local precedence order
is partial or total the leftmost siblings must come first. Therefore
no sibling to the right of a candidate can be a candidate. In CLOS
the local precedence order is total on the class itself and its direct
siblings. The union of the local precedence orders might be a partial
ordering and it might be a total ordering.
My example of green-turtles was completely bogus, so forget it.
I still think, though, that people will still regard the CPL computation
as a black box. The example at the start of this message shows that
intuition isn't going to help much in all cases.
-rpg-
∂01-Feb-87 2257 edsel!bhopal!jonl@navajo.stanford.edu CPL anxieties
Received: from NAVAJO.STANFORD.EDU by SAIL.STANFORD.EDU with TCP; 1 Feb 87 22:57:34 PST
Received: by navajo.stanford.edu; Sun, 1 Feb 87 22:56:38 PST
Received: from bhopal.edsel.com by edsel.uucp (2.2/SMI-2.0)
id AA04633; Sun, 1 Feb 87 22:36:57 pst
Received: by bhopal.edsel.com (3.2/SMI-3.2)
id AA04283; Sun, 1 Feb 87 22:40:28 PST
Date: Sun, 1 Feb 87 22:40:28 PST
From: edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)
Message-Id: <8702020640.AA04283@bhopal.edsel.com>
To: navajo!common-lisp-object-system%SAIL.STANFORD.EDU@navajo.stanford.edu
Subject: CPL anxieties
Gabriels "green, animate turtles" diagram is super-simplification of
the example I showed several people at the Boston meeting in Dec 1985;
Danny had actually seen it earlier that year. The oversimplification
was the joining of the superclasses at the second level; because of that,
the depth-first **up to join** type algorithms will in fact become breadth
first on it [which is the desired behaviour!].
A closer approximation to the troubling scenario is below, which has no
super-class hierarchy drawn above the third level. Then Dick's commentary
and criticisms apply exactly to it. That is, any algorithm which tries to
preserve the property that "inherited methods are indistinguishable from
present methods" will have to place at least some of the super-super-classes
before one of the direct supers, and thus the resulting order will not be
breadth-first.
This example may be related to the problem of "shadowing methods", which
hasn't yet been addressed, but which some people feel is important.
(defclass Animate-things (. . . ) ()) ;has possibly many suprs
(defclass Colored-things (. . . ) ()) ;has possibly many suprs also
(defclass Turtles (Animate-things) ())
(defclass Green-things (Colored-things) ())
(defclass Green-turtles (Turtles Green-things) ())
.
.
. .
Animate-things .
blush-method = turn-pink .
| .
| Colored-things
| noseup-method = become-haughty
| |
/ \
Turtles Green-things
noseup-method = pick-up-pen blush-method = turn-purple
\ /
\ /
\ /
|
|
Green-turtles
I presume everyone can see the conflict which will arise if the two
direct supers to Green-turtles don't directly follow the class itself.
One way to view this situation is that Green-turtles is a contradictory
class, because it would inherit, say, a blush-method from two distinct
suprs -- from Green-things and from Animate-things. Another view is
that the present methods of the direct suprs are "more important and
shadow any "higher" up. A third view is that the user ought to be
able to distinguish such situations in his program in a simple way.
If you are of the first opinion, then a good question to ask yourself
is "Why does the conflict go away when I merge the class Colored-things
into the class Animate-things? Should it?"
The basic problem is the rigidity and complexity of the CPL algorithm. In
some (unlikely) choices of supers for Animate-things and for Colored-things,
it may be that the CPL will fortuitously be
(Green-turtles Turtles Green-things . . .)
but if so, the user will probably have no way of understanding why. He
will certainly complain that there is no comprehensible way to control
the CPL algorithm when it produces an ordering with some random super-super
ahead of one of the two direct supers. No easily-comprehensible way to
control CPL means essentially no control over inheritance, which means,
again, a "black box of unpredicibility, like Flavors".
-- JonL --
[Regarding the impredicability of Flavors-type inheritance -- I know KDO
fairly well know, and wouldn't accuse him of shallow understanding. If he
had to tweak flavors classes in an unknowing way to get the desired behaviour
out of them, it was because there was no reasonably comprehensible way to
program the desired behaviour.]
∂02-Feb-87 0854 RPG Re: ---
∂02-Feb-87 0818 Bobrow.pa@Xerox.COM Re: ---
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Feb 87 08:17:57 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 JAN 87 13:57:55 PST
Date: 30 Jan 87 13:57 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: ---
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 30 Jan 87
12:59 PST
To: RPG@SAIL.STANFORD.EDU
cc: bobrow.pa@Xerox.COM
Message-ID: <870130-135755-132@Xerox>
in-degree is class-dependent. It is stored in the class
data structure someplace.
So it is computed each time the class precedence list is
changed??? Is it used for anything else.
danny
No.
So one could as easily use my double recursive program with a hashtable
for visited (constructed on the one visit through all the classes),
rather than constructing a separate in degree.
But who cares really. I think I was just being too clever (I like
doubly recursive programs). I think Moon's new rule, restated clearly
as I know you will do, is fine. We now have criteria (your restatement
of my concern with Moons addition certainly clarified my intent). I
think we are in good shape. Onward and downward.
danny
∂02-Feb-87 1617 Bobrow.pa@Xerox.COM Re: Method Combination
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Feb 87 16:16:01 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 JAN 87 15:30:22 PST
Date: 30 Jan 87 15:30 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Method Combination
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-system@SAIL.STANFORD.EDU
Message-ID: <870130-153022-143@Xerox>
Dave and I had a telephone conversation today to discuss the outstanding
issues of define-method-combination (mostly because there were things I
didn't understand). My understanding of the agreement we came to
follows. Dave please comment if you think I have misrepresented any
part.
1) Syntax of define-method-combination:
(d-m-c name lambda-list method-group-specifiers doc/decl* form*)
as is specified in current document.
However, lambda-list is an internal lambda list used ONLY for parsing of
extra parameters supplied to compute-effective-method. It does not
include a name for the generic-function. The well-known-name
"generic-function" is available for use within the
define-method-combination forms.
The argument list of compute-effective-method is
(generic-function combination-name applicable-methods &optional params)
define-method-combination implicitly defines a specialized method for
compute-effective-method, using lambda-list as an internal lambda-list
to destructure, bind and error check the params argument for
compute-effective-method.
(d-m-c name lam-list ((v1 v1-pat)(v2 v2-pat ..)...) . body)
expands to approximately
(defmethod
((generic-function standard-generic-function)
(c-type (quote name))
applicable-methods
&optional params)
(declare (special generic-function)) ;; is this declaration right
((lambda lam-list
(let ((methods-left applicable-methods)
v1 v2 ...)
(multiple-value-setq v1 methods-left
(select-methods methods-left 'v1-pat ...))
(multiple-value-setq v2 methods-left
(select-methods methods-left 'v2-pat ...))
...
(AND methods-left (method-combination-error...))
. body)
params))
2) Support of around methods
We agreed that the make-method-call form made it easy enough to
support :around methods, so no further syntax was needed. We agreed
that we would use
:operator :call-next-method
in make-method-call as the way to indicate call-next-method combination.
We will eliminate the :around keyword from make-method-call.
3) We disagreed whether the standard should have only one form of
define-method-combination (danny thought Yes, dave No), but Dave agreed
to put the short form second in the document, and to describe it mostly
in terms of its expansion to the long form. Dave said he would think
about renaming the short form, for example to define-simple-combination.
4) I agreed that Moon's rule for CPL, although not as easy to understand
as I might like, captured the criteria I wanted to preserve for the
class precedence list. I am happy to stop worrying about this problem.
∂02-Feb-87 1621 Gregor.pa@Xerox.COM Some other open issues
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Feb 87 16:18:00 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 JAN 87 17:14:26 PST
Date: 30 Jan 87 15:51 PST
From: Gregor.pa@Xerox.COM
Subject: Some other open issues
To: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <870130-171426-101@Xerox>
I believe we have to get the initialization stuff in the spec by RPG's
deadline. We also need to haev time to talk about it, and fix the
examples to use it, and document make-instance when the first argument
is one of (STANDARD-METHOD STANDARD-GENERIC-FUNCTION STANDARD-CLASS),
and to just think about it. I think this is more important than
polishing method combination or class-precedence-list stuff.
An issue which is less important, is a portable interface to the code
walker so that people can make their own versions of with-slots. The
last time we talked about this it became a big debate about how to write
macros. This probably doesn't need to be done by RPG's deadline, but I
wanted to remind us that it was something we said we would do.
∂02-Feb-87 1624 Bobrow.pa@Xerox.COM Re: Minor things noticed while proofreading documents
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Feb 87 16:16:21 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 JAN 87 15:39:07 PST
Date: 30 Jan 87 15:38 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Minor things noticed while proofreading documents
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 30 Jan 87 00:50 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870130-153907-143@Xerox>
slot-spec syntax: did (slot-name initform) as a convenient
abbreviation for (slot-name :initform initform) go away
accidentally, or did we really decide to get rid of it? I don't
remember discussing this.
I thought this was still supposed to be there, but I don't care.
:accessor-prefix, :reader-prefix: the document says that the
argument to these can be a string, a symbol, or nil. My memory is
that we got rid of the string and nil cases. True or false?
We certainly agreed to flush strings. We need to be able to say that the
slot-names themselves are used for the accessors. If (:accessor-prefix)
is used for that, we do not need NIL. I vote for (:accessor-prefix) as
the right way to say use the slot-names.
The documentation for get-method says that the specializers
argument is a list of parameter specializers. I proposed an alist
format instead, to allow extensibility to specializing on keyword
arguments in the future. I thought it was accepted. Was it
rejected, or did the document just not get updated yet? This
applies to make-method also.
I thought we said one could extend the parameter specializers list by
putting in &key and using an alist for those specializers later, and
this way the user does not have to specify argument names.
Should make-generic-function and make-method be flushed in
favor of documenting particular sets of arguments to make-instance
that perform those functions?
I favor this. slot-names in the standard meta-objects should be used.
danny
∂02-Feb-87 1634 Bobrow.pa@Xerox.COM Re: Gregor's comments on some things
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Feb 87 16:18:42 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 JAN 87 17:31:15 PST
Date: 30 Jan 87 16:06 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Gregor's comments on some things
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 29 Jan 87 22:58 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870130-173115-103@Xerox>
What does the phrase "x is of class array mean"? In
the first paragraph of the section Integrating Types and
Classes in Concepts (draft of 1/23) it is used to mean "x is of
class array or some subclass of array"? Is that official?
I think so. I believe "X is of class Y" and "X is an instance
of Y" mean that (class-of X) is Y or a subclass of Y, rather than
(eq (class-of X) Y).
This whole terminology issue would be easier if we up front indicated
that classes are used to reify Common Lisp types specified by (most of)
the type specifer symbols. Hence, we could use the expression "x is of
type array" in its usual sense (any subtype will do), and
(typep x (class-name class))
is the same as
(classp x class)
What do you think about extending typep to allow
(typep x class).
Another implication of going to this terminology is that we could say
class C1 is a subtype of class C2 meaning that C1 is C2 or is some
subclass of C2.
Another terminological suggestion. To eliminate the two uses of the
term "metaclass", I suggest that we reserve metaclass to mean a class
whose instances are classes, and use the term "metatype" to refer to the
relationship of an instance to the class of its class, that is
"it is the metatype of an instance that determines its implementation."
Well, it's pretty weird that symbols are turned into class
objects but QUOTE-expressions are not. This doesn't generalize
very well to the extension to supporting other Common Lisp type
specifiers.
This does generalize in the sense that classes correspond to type
symbols, and list expressions correspond to list type specifiers.
(QUOTE X) means (MEMBER (X)). Thus the language generalizes in
correspondence to CLtL. A second answer is that this is the internal
representation of add-method etc. and is designed to keep dependence on
names
Of course it makes get-method and related functions useless
until we put in the supporting functions such as class-named. Is
there any reason that these aren't documented already?
I sent one message describing them already. The only issue I know is
what class-name should do if the class has no name. Two options are:
1) Signal an error
2) class-name has a second optional argument which is the value returned
if class has no name.
(class-named name &optional no-error-flag)
returns the class with the name given or signals an error.
Do you Gregor, or anyone else, have a list of these missing
functions? I'm not talking about the full meta-object protocol,
just the functions needed to program at the next level of
abstraction below the defxxx macros.
I will get a message out about these.
danny
∂02-Feb-87 1636 Gregor.pa@Xerox.COM Some other open issues
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Feb 87 16:19:26 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 JAN 87 18:02:44 PST
Date: 30 Jan 87 15:51 PST
From: Gregor.pa@Xerox.COM
Subject: Some other open issues
To: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <870130-180244-104@Xerox>
I believe we have to get the initialization stuff in the spec by RPG's
deadline. We also need to haev time to talk about it, and fix the
examples to use it, and document make-instance when the first argument
is one of (STANDARD-METHOD STANDARD-GENERIC-FUNCTION STANDARD-CLASS),
and to just think about it. I think this is more important than
polishing method combination or class-precedence-list stuff.
An issue which is less important, is a portable interface to the code
walker so that people can make their own versions of with-slots. The
last time we talked about this it became a big debate about how to write
macros. This probably doesn't need to be done by RPG's deadline, but I
wanted to remind us that it was something we said we would do.
∂02-Feb-87 1645 RPG Various of Danny's Comments
To: common-lisp-object-system@SAIL.STANFORD.EDU
Danny writes:
``However, lambda-list is an internal lambda list used ONLY for parsing of
extra parameters supplied to compute-effective-method. It does not
include a name for the generic-function. The well-known-name
"generic-function" is available for use within the
define-method-combination forms.''
I think this is pretty lousy. Having special hidden arguments is bad in
the same way that non-local references to variables are. What does ``ONLY
for parsing of extra parameters'' mean? Are we really going to put the
meta-object function COMPUTE-EFFECTIVE-METHOD into CONCEPTS and FUNCTIONS?
Danny writes:
``I vote for (:accessor-prefix) as the right way to say use the
slot-names.''
To quote a famous computer scientist, ``ugh, bletch.''
-rpg-
∂02-Feb-87 1636 Gregor.pa@Xerox.COM Some other open issues
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Feb 87 16:19:06 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 30 JAN 87 17:59:40 PST
Date: 30 Jan 87 15:51 PST
From: Gregor.pa@Xerox.COM
Subject: Some other open issues
To: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <870130-175940-103@Xerox>
I believe we have to get the initialization stuff in the spec by RPG's
deadline. We also need to haev time to talk about it, and fix the
examples to use it, and document make-instance when the first argument
is one of (STANDARD-METHOD STANDARD-GENERIC-FUNCTION STANDARD-CLASS),
and to just think about it. I think this is more important than
polishing method combination or class-precedence-list stuff.
An issue which is less important, is a portable interface to the code
walker so that people can make their own versions of with-slots. The
last time we talked about this it became a big debate about how to write
macros. This probably doesn't need to be done by RPG's deadline, but I
wanted to remind us that it was something we said we would do.
∂02-Feb-87 1920 Bobrow.pa@Xerox.COM Re: Various of Danny's Comments
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Feb 87 19:18:53 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 02 FEB 87 17:42:21 PST
Date: 2 Feb 87 17:42 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Various of Danny's Comments
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 02 Feb 87
16:45 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870202-174221-1368@Xerox>
I think this is pretty lousy. Having special hidden arguments
is bad in the same way that non-local references to variables are.
What does ``ONLY for parsing of extra parameters'' mean? Are we
really going to put the meta-object function
COMPUTE-EFFECTIVE-METHOD into CONCEPTS and FUNCTIONS?
All that has to be said in the concepts or functions chapter is that
"generic-function" is a well-known name. Within the body of
define-method-combination, extra parameters in the def-generic-option
:method-combination option are bound to the variables provided in the
lambda-list in define-method-combination.
``I vote for (:accessor-prefix) as the right way to say use the
slot-names.''
To quote a famous computer scientist, ``ugh, bletch.''
Vell, you got xomething better. We have two cases for names:
1) Create symbols for each of the methods (accessors) specified. Make
these symbols by interning the concatenation of prefix with the
slot-name. Intern the symbols in the package of the specified prefix.
2) Use the names of the slots for the accessors.
For the first we use (:accessor-prefix <symbol>)
For the second which special case do you like:
a) (:accessor-prefix)
b) (:accessor-prefix nil)
c) (:accessor-prefix ||)
Of these three ugly choices, I prefer the first. The second and third
have symbols that are interned in some package, and hence violate the
interning rule.
b) (:accessor-prefix nil)
c) (:accessor-prefix ||)
Of these three ugly choices, I prefer the first. The second and third
have symbols that are interned in some package, and hence violate the
rule.
danny
∂02-Feb-87 1920 Bobrow.pa@Xerox.COM Re: CPL Varia
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Feb 87 19:19:30 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 02 FEB 87 18:36:57 PST
Date: 2 Feb 87 18:36 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: CPL Varia
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 01 Feb 87
14:10 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870202-183657-1455@Xerox>
Given that Moon has agreed that the example
(defclass c1 (top) ())
(defclass c2 (top) ())
(defclass c3 (top) ())
(defclass d1 (c1 c2) ())
(defclass d2 (c1 c3) ())
(defclass e1 (d1 d2) ())
producing the CPL (E1 D1 D2 C1 C3 C2 TOP) is ok, I am willing
to accept it. I will make sure the writeup is reasonable.
I agree too. Thank you. I am glad to see this reach closure.
danny
∂02-Feb-87 1925 masinter.PA@Xerox.COM Re: Common Lisp Types
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Feb 87 19:16:17 PST
Received: from Chardonnay.ms by ArpaGateway.ms ; 02 FEB 87 08:29:37 PST
From: masinter.PA@Xerox.COM
Date: 2 Feb 87 8:29:19 PST
Subject: Re: Common Lisp Types
In-reply-to: RPG@SAIL.STANFORD.EDU's message of 31 Jan 87 09:23 PST
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870202-082937-171@Xerox>
Didn't you get my mail on this issue?
Should I resend it?
∂02-Feb-87 1925 Masinter.pa@Xerox.COM Re: Common Lisp Types
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Feb 87 19:18:19 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 02 FEB 87 15:55:24 PST
Date: 2 Feb 87 15:58 PST
From: Masinter.pa@Xerox.COM
Subject: Re: Common Lisp Types
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 31 Jan 87
09:23 PST
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870202-155524-1154@Xerox>
Strategy: We're better off leaving out classes where we have some doubts
than putting them in. New classes can be added easily later, but its
hard to get rid of things later.
Most of the classes ommitted don't belong, but for different reasons
than given:
-- types where the "type" of an object can change without going through
the change-class protocol, e.g., satisfies. Keyword is here because it
is not an error to change a keyword's home package.
-- union types (or ...) are ommitted for now because there is no natural
ordering for two different union types. Included in this is the
predefined union type COMMON.
-- range types. These include integer, floating ranges like (integer 3
12). These are omitted for the same reason that union types are omitted.
They include the predefined range types bit and fixnum. Also ommitted is
the type standard-char, which is a fairly arbitrary subset of
characters.
-- negation types. For similar reasons, types which are merely defined
as the negation of others are omitted. These include types of the form
(not x), atom, which is (not cons), and bignum, which is (and integer
(not fixnum))
We can include those implementation-dependent subclasses which have
portable language semantics: string-char, short-float, long-float,
double-float, single-float. [This is a different position than that in
the current paper.]
I much prefer having the CLOS description for function, stream (and
pathname?) be done 'right' but conditional on a corresponding cleanup of
CL than having a standard class which no implementation is required to
use or generate.
The issue is, what do you get when you say (class-of '(lambda --)). If
you insert function in the class hierarchy with RPG's definition, you
get LIST. However, this seems to violate what I think of as an
invariant, namely
for all objects x, for all classes y, (subtypep (class-of x) y) ==
(typep x y)
"For functions, I propose that the Class Function include as instances
those objects in the Lisp that are in the range of the function
Function.
For many implementations this will coincide with Compiled-Function,
which
would be a subclass of Function. This means that CLOS adopts the
attitude
that symbols and lists that happen to represent functions are the
second-class
version of functions."
In RPG's proposal, without a corresponding change to CL, you could get
back from
(function (lambda ...)) a list (lambda ...) for which class-of would
return the class LIST, which is not a sub-class of function.
∂02-Feb-87 1927 Bobrow.pa@Xerox.COM Re: Common Lisp Types
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Feb 87 19:19:47 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 02 FEB 87 18:43:21 PST
Date: 2 Feb 87 18:43 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Common Lisp Types
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 31 Jan 87
09:23 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870202-184321-1467@Xerox>
In particular, the current Design Rationale chapter says there
are no classes for these things:
`` - Types too specific to be useful to put methods on:
bit, keyword, standard-char, string-char
I think that we must consider the rationales I gave in my message of 22
Jan 87 15:10 PST. For this case the problem is:
"c) The class of any instance should be quickly determinable. Thus
standard-char might be a case which is outlawed since it is a char that
is member of a set. Probably bit (represented by an integer that is
either 1 or 0) also falls in this category."
- Specification of the type is too vague: common, function, stream
Here the problem is whether the user is in for a surprise.
For functions, I propose that the Class Function include as
instances those objects in the Lisp that are in the range of the
function Function. For many implementations this will coincide with
Compiled-Function, which would be a subclass of Function. This
means that CLOS adopts the attitude that symbols and lists that
happen to represent functions are the second-class version of
functions.
"a) all instances of the class (or any subclass) can be identified as
being of that type. FUNCTION has a problem in that respect wrt lists. "
Perhaps we want to have methods on compiled-function.
With these two exceptions I agree with the points expressed by Dick in:
I propose that every
implementation be required to provide the classes explicitly
excluded in the design rationale except for negation classes (atom)
and Common, though there may be no instances of them, and I presume
we can arrange for the metaclass to state that fact. Furthermore, I
propose that the structure of the lattice in the vicinity of
implementation-dependent types be variable, reflecting the
implementation hierarchy. For example, if an implementation has
single-floats only, the classes would be:
(defclass short-float (single-float)) (defclass long-float
(single-float)) (defclass double-float (single-float)) (defclass
single-float (float))
and only single-float would have instances. The other
permissible float configurations have different topology.
I propose that the class named NIL be at the bottom of the
lattice and that it also has no instances.
danny
∂02-Feb-87 1935 Masinter.pa@Xerox.COM Re: symbols are not generic functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Feb 87 19:17:57 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 02 FEB 87 13:35:55 PST
Date: 2 Feb 87 13:37 PST
From: Masinter.pa@Xerox.COM
Subject: Re: symbols are not generic functions
In-reply-to: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET's message of 30 Jan
87 11:00:25
To: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870202-133555-227@Xerox>
that seems awfully complicated for something that is of mainly internal
benefit. Also, it continues to confound the use of symbols vs functions.
The :error-if kinds of keyword arguments are generally a last-resort
technique -- you know if you need them that something is busted.
∂02-Feb-87 1952 Bobrow.pa@Xerox.COM Re: CPL anxieties
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Feb 87 19:19:01 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 02 FEB 87 18:34:50 PST
Date: 2 Feb 87 18:34 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: CPL anxieties
In-reply-to: edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)'s
message of Sun, 1 Feb 87 22:40:28 PST
To: edsel!bhopal!jonl@navajo.stanford.edu
cc:common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870202-183450-1444@Xerox>
(defclass Animate-things (. . . ) ()) ;has possibly many suprs
(defclass Colored-things (. . . ) ()) ;has possibly many suprs also
(defclass Turtles (Animate-things) ())
(defclass Green-things (Colored-things) ())
(defclass Green-turtles (Turtles Green-things) ())
.
.
. .
Animate-things .
blush-method = turn-pink .
| .
| Colored-things
| noseup-method = become-haughty
| |
\
Turtles Green-things
noseup-method = pick-up-pen blush-method = turn-purple
\ /
\ /
\ /
|
|
Green-turtles
I presume everyone can see the conflict which will arise if the
two direct supers to Green-turtles don't directly follow the class
itself. One way to view this situation is that Green-turtles is a
contradictory class, because it would inherit, say, a blush-method
from two distinct suprs -- from Green-things and from
Animate-things. Another view is that the present methods of the
direct suprs are "more important and shadow any "higher" up. A
third view is that the user ought to be able to distinguish such
situations in his program in a simple way.
If you are of the first opinion, then a good question to ask
yourself is "Why does the conflict go away when I merge the class
Colored-things into the class Animate-things? Should it?"
If the currently proposed algorithm is used, you will not be able to see
the difference between merging turtle and animate-thing, and/or merging
gren and colored things. The order proposed puts both turtle and
animate before both green and colored, so the latter two will have no
effect wrt the two methods of concern. I claim this is correct.
The CPL algorithm as I now undertand it preserves:
1) subclasses go before superclasses
2) local precedence order is preserved
3) if two sublattices from two classes that have have no members in
common, then all members of one sublattice occur before all the members
of the other. This preserves the invariant that a program should not
change if you just split the functionality of a class into any number of
subclasses.
danny
∂02-Feb-87 2053 RPG Common Lisp Types
To: common-lisp-object-system@SAIL.STANFORD.EDU
When I feel conservative, I agree with Larry's message. When I want
to stir up the CL community, I disagree. His message is well-reasoned
and it probably makes sense to simply adopt his stance. However, let's
consider stirring up the hornets:
Larry writes:
``[we should eliminate] types where the "type" of an object can change
without going through the change-class protocol, e.g., satisfies. Keyword
is here because it is not an error to change a keyword's home package.''
The people writing code that distinguishes keywords from other things
and that can break if objects change classes `unexpectedly'
consider themselves wizards. I don't care about their bugs.
Larry remarks that the range of FUNCTION could be weird. My desire
to have CLOS specify some better treatment of functions is partially
a desire to humiliate the CL crowd into wanting to fix functions.
Larry writes:
``In RPG's proposal, without a corresponding change to CL, you could get
back from (function (lambda ...)) a list (lambda ...) for which class-of would
return the class LIST, which is not a sub-class of function.''
You bet, and I would think users would start to lobby against a
CL that did that. Make 'em sweat!
Larry writes:
``Also ommitted is the type standard-char, which is a fairly arbitrary
subset of characters.''
Even though they are arbitrary, some people might want to write portable
but system-dependent code that reasons about such arbitrary decisions.
-rpg-
∂02-Feb-87 2224 edsel!bhopal!jonl@navajo.stanford.edu CPL anxieties
Received: from NAVAJO.STANFORD.EDU by SAIL.STANFORD.EDU with TCP; 2 Feb 87 22:19:21 PST
Received: by navajo.stanford.edu; Mon, 2 Feb 87 22:18:25 PST
Received: from bhopal.edsel.com by edsel.uucp (2.2/SMI-2.0)
id AA07825; Mon, 2 Feb 87 21:52:17 pst
Received: by bhopal.edsel.com (3.2/SMI-3.2)
id AA06846; Mon, 2 Feb 87 21:55:47 PST
Date: Mon, 2 Feb 87 21:55:47 PST
From: edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)
Message-Id: <8702030555.AA06846@bhopal.edsel.com>
To: navajo!Bobrow.pa%Xerox.COM@navajo.stanford.edu
Cc: navajo!common-lisp-object-system%SAIL.STANFORD.EDU@navajo.stanford.edu
In-Reply-To: Danny Bobrow's message of 2 Feb 87 18:34 PST
Subject: CPL anxieties
Re: If the currently proposed algorithm is used, you will not be able to see
the difference between merging turtle and animate-thing, and/or merging
gren and colored things. . . .
The "anxiety" followed from merging Colored-things and Animate-things,
rather than either of those with their direct inferiors. When they are
merged (and they have no similar methods so it would be a disjoint
merger), then the "up to join" nature of the pre-order treewalk forces
a semi-breadth-first ordering. Which is what the original source of
this example was trying to achieve.
Re . . . The order proposed puts both turtle and
animate before both green and colored, so the latter two will have no
effect wrt the two methods of concern. I claim this is correct.
This is simply the depth-first order. While it enforces *some* ordering
on the problem, there is no reason in the topology of the inheritance
graph to believe that one ordering is preferable to another. In such
circumstances, either there are some methods which would be inherited from
essentially *incomparable* classes, or there are no such methods. In the
latter case, it is a "moot" point, but in the former, shouldn't an error
of some sort be signalled? or shouldn't there be some way for the user
to specify more exactly what he wants?
The anxieties, then, can be summarized as
1) defining a "mix in" subclass forces the programmer to specify an order
among the direct suprs; but this ordering may have no relation whatsoever
to the application problem, and it will probably determine all the
method inheritance choices.
2) merging/spliting a class "way up" in the inheritance graph can override
what methods the new class has; but the programmer wanted to be able to
say something (anything?) which would insure the selection of the correct
blush and pen-up methods.
Maybe there should be an "unordered" defclass, for which the CPL is built
exactly like in the "ordered" case, but for which the error signalling
conditions might be more stringent.
-- JonL --
∂03-Feb-87 1203 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Moon/Bobrow phone conversation
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 3 Feb 87 12:00:03 PST
Received: from ti-csl by csnet-relay.csnet id ak05669; 3 Feb 87 14:48 EST
Received: from dsg (juliett.ARPA) by tilde id AA03965; Mon, 2 Feb 87 17:39:55 cst
Received: FROM Jenner BY dsg Via CHAOS-NET with CHAOS-MAIL; 2-Feb-87 10:32:56
Message-Id: <2748270803-690773@Jenner>
Sender: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Date: 2-Feb-87 10:33:23
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Common-Lisp-Object-System@SU-AI.ARPA
Subject: Re: Moon/Bobrow phone conversation
In-Reply-To: In-Reply-To: Msg of 31-Jan-87 22:52:00 from "David A. Moon" <Moon@scrc-stony-brook.arpa>Msg of 31-Jan-87 22
Date: 31-Jan-87 22:52:00
From: "David A. Moon" <Moon@scrc-stony-brook.arpa>
I made some changes to define-method-combination that Danny Bobrow and I
discussed on the phone. The generic-function is no longer in the lambda
list, instead it's a wired-in variable name. The lambda-list is still
present for expansion, but is () in standard method combination. The
short form is described after the long form and the expansion into the
long form is shown. compute-effective-method takes 4 arguments.
:operator :call-next-method replaces :around t in make-method-call.
The short form takes the operator as a keyword argument instead of a
positional argument. I think we all agree on this compromise now.
It's OK with me. I am glad to see this issue resolved.
Patrick.
∂03-Feb-87 1354 RPG Clarification
To: common-lisp-object-system@SAIL.STANFORD.EDU
LGD and I are going over the CONCEPTS file. The following
sentence appears:
``The slot options provided by the various slot descriptions combine as
follows:
{\bf :allocation} comes from the most specific slot description in the
class precedence list---if it does not explicitly specify {\bf
:allocation}, the default is {\bf :allocation} {\bf :instance}.''
We propose the following fair copy:
``The slot options provided by the various slot descriptions combine as
follows:
The {\bf :allocation} option is inherited from the most specific class
in the class precedence list. If no superclass explicitly specifies
the {\bf :allocation} option, the default is {\bf :allocation}
{\bf :instance}.''
Note that this definition is intended to be recursive, because there might
be no class that explicitly specifies the :allocation option.
Any objections?
-rpg-
∂03-Feb-87 1431 Gregor.pa@Xerox.COM Re: Clarification
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 3 Feb 87 14:26:03 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 03 FEB 87 14:12:35 PST
Date: 3 Feb 87 14:12 PST
From: Gregor.pa@Xerox.COM
Subject: Re: Clarification
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 03 Feb 87
13:54 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870203-141235-2721@Xerox>
Your "fair text" describes completely different inheritance rules. The
case in particular, as I outlined in my message on slot inheritance the
other day is:
(defclass foo ()
((a :allocation :class)))
(defclass bar (foo)
((a :initform ()))
Under the rules currently in the document, and the rules I mailed out
the other day:
instances of the class foo share a :class variable named a
instances of the class bar each have their own :instance variable a
Under the rules you propose its unclear what would happen. Perhaps
their would be two class variables, perhaps there would be one, its not
clear what would happen with :initform.
The rules described in the document should not be changed in substance.
I have only read them once, but they seem to match the rules which Danny
and I came up with and which I mailed out the other day.
∂03-Feb-87 1555 Bobrow.pa@Xerox.COM Re: Clarification
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 3 Feb 87 15:55:49 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 03 FEB 87 14:34:35 PST
Date: 3 Feb 87 14:34 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Clarification
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 03 Feb 87
13:54 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870203-143435-2787@Xerox>
We propose the following fair copy:
``The slot options provided by the various slot descriptions
combine as follows:
The {\bf :allocation} option is inherited from the most
specific class in the class precedence list. If no superclass
explicitly specifies the {\bf :allocation} option, the default is
{\bf :allocation} {\bf :instance}.''
Note that this definition is intended to be recursive, because
there might be no class that explicitly specifies the :allocation
option.
The only issue this skirts is the following example that has a problem:
(defclass A () ((s :initform 1 :allocation :class)))
(defclass B (A)((s :initform 2)))
The latter MUST mean :allocation :instance (or signal an error). I
think we should insist that :allocation :class be repeated if it is
intended to change anything else about the class variable (this is the
only sane semantic interpretation). Another alternative is to make
there be a different class variable in B.
For :dynamic, this kind of example makes sense (there is a different
value stored in a different class). But on the principle that the
unusual case (namely anything but :allocation :instance) ought to be
visible locally. I would say that if a local description appears in a
class, then allocation is :instance, unless overridden locally. Or
stronger, if allocation inherited is anything but :instance, then an
error is signalled if no :allocation is specified locally. Which of
these two do you like?
∂03-Feb-87 1945 kempf%hplabsc@hplabs.HP.COM Re: Some other open issues
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 3 Feb 87 19:41:07 PST
Received: from hplabsc by hplabs.HP.COM ; Tue, 3 Feb 87 19:38:45 pst
Received: by hplabsc ; Tue, 3 Feb 87 19:38:29 pst
Date: Tue, 3 Feb 87 19:38:29 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8702040338.AA08376@hplabsc>
To: Common-Lisp-Object-System@Sail.stanford.edu, Gregor.pa@Xerox.COM
Subject: Re: Some other open issues
I agree with Gregor about the portable code walker interface not
being necessary for the deadline, however, I would like to point
out that it may be desirable to press the issue of a symbol macro
special form for Common Lisp.
The reason I mention this is because some recent profiling results
I have from PCL indicate that the code walker is in the top two
or three slowest functions called during method generation. Addition of
a symbol macro special form (called LET-PSEUDO in our system)
would allow the compiler to take care of substituting the proper
form for slot access when a WITH is processed. So proper resolution
of this issue may impact the efficiency of method generation in
Classes, as well as the potential for extention using the metaclass
protocol.
Obviously, this issue need not be resolved until more important
semantic issues are.
Jim Kempf kempf@hplabs.hp.com
∂04-Feb-87 0810 kempf%hplabsc@hplabs.HP.COM Re: Common Lisp Types
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 4 Feb 87 08:07:32 PST
Received: from hplabsc by hplabs.HP.COM ; Wed, 4 Feb 87 08:06:36 pst
Received: by hplabsc ; Wed, 4 Feb 87 08:06:25 pst
Date: Wed, 4 Feb 87 08:06:25 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8702041606.AA20595@hplabsc>
To: Bobrow.pa@Xerox.COM, RPG@SAIL.STANFORD.EDU
Subject: Re: Common Lisp Types
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
From the application programmer's viewpoint, classes for some of
the types listed as not having any would make application development
using CLOS more straightforward. Consider the STREAM type. If
a STREAM class exists, and is subclass-able, then developing
a window system application which can run on a variety of displays
becomes easier, since WINDOW can be a subclass of STREAM. In
this sense, I think Gabrial's proposal is a sound one, since it
increases the integration between the CL type system and CLOS.
Jim Kempf kempf@hplabs.hp.com
∂04-Feb-87 0953 DLW@RIVERSIDE.SCRC.Symbolics.COM initializing class slots
Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 4 Feb 87 09:53:07 PST
Received: from CHICOPEE.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 98755; Wed 4-Feb-87 12:07:53 EST
Date: Wed, 4 Feb 87 12:05 EST
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: initializing class slots
To: Bobrow.pa@Xerox.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870203-143435-2787@Xerox>
Message-ID: <870204120512.0.DLW@CHICOPEE.SCRC.Symbolics.COM>
Line-fold: No
Date: 3 Feb 87 14:34 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
(defclass A () ((s :initform 1 :allocation :class)))
By the way, I could not find anything specific in the document that says
how initforms work for class slots. For example, exactly when is the
initform evaluated? At the time of the evaluatino of the containing
defclass?
∂04-Feb-87 0956 Bobrow.pa@Xerox.COM Re: Common Lisp Types
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Feb 87 09:56:30 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 04 FEB 87 09:40:11 PST
Date: 4 Feb 87 09:39 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Common Lisp Types
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Wed, 4
Feb 87 08:06:25 pst
To: kempf%hplabsc@hplabs.HP.COM
cc: Bobrow.pa@Xerox.COM, RPG@SAIL.STANFORD.EDU,
common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870204-094011-3744@Xerox>
From the application programmer's viewpoint, classes for some
of the types listed as not having any would make application
development using CLOS more straightforward. Consider the STREAM
type. If a STREAM class exists, and is subclass-able, then
developing a window system application which can run on a variety
of displays becomes easier, since WINDOW can be a subclass of
STREAM. In this sense, I think Gabrial's proposal is a sound one,
since it increases the integration between the CL type system and
CLOS.
Jim Kempf kempf@hplabs.hp.com
I believe having abstract classes is great. The problem becomes when
the user expects a method to be applicable, but it isn't because the
type (class) system doesn't preserve the appropriate subclass
relationships. For example, will the type (class) system support
(subclassp (class-of #'(lambda(x) x)) (class-named 'function))
If so, then function is a good class; if not, then I think there is
some confusion. If all implementations of stream are such that
(subclassp (class-of *stream-object*) (class-named 'stream))
then stream is a good class.
Thus, I believe in most of what RPG suggested. But we should be careful
not to break the users model of the class system.
danny
∂04-Feb-87 1004 RPG Inheritance of Slot Options
To: common-lisp-object-system@SAIL.STANFORD.EDU
I think the current spec suffers from excessive rules for the sake
of marginal functionality. I propose this slight modification:
We break what was slot options into two categories, slot descriptions
and slot options (in the BNF, what was ``slot options'' becomes ``slot
descriptor''). Slot options are the :accessor and :reader guys. Slot
descriptions are :initform, :allocation, and :type. The slot options
are as before. Slot description inherit like this:
Let CPL be the class precedence list for C. If C's defclass doesn't have a
slot descrption for a slot it is totally inherited from the next most
specific class in the CPL. If C's defclass has a slot description, it
totally shadows any other in CPL. When this latter case happens, some of
the aspects of the slot description might be defaulted. The defaulting is
as follows:
:initform is defaulted to unsupplied
:allocation is :instance
:type is T
The effective type of a slot is the AND of all types specified for it
in the CPL.
There are two differences between this and the previous rule (which I now,
unfortunately, understand). First, :initform acts differently - if you want
to change the :type or :allocation and keep the :initform, you have to mention
the :initform again. Second, it is an easier rule to understand and remember.
I think it's counterproductive to have a complex set of rules to enforce
some intuition that doesn't pay its own way. A simpler but slightly inaccurate
model, where the inaccuracy to someone's intuition is unimportant, is
preferrable to a complex model that captures someone's epicycle.
-rpg-
∂04-Feb-87 1138 RPG Addendum to ``Inheritance of Slot Options''
To: common-lisp-object-system@SAIL.STANFORD.EDU
I forgot to mention in my last message that :allocation :none
should be flushed as well, because the current ``rules'' for
it are not as wonderful as someone might like. If we (democratically construed)
decide to keep :allocation :none, I think the rule I proposed in the
last message is adequate; possibly someone should remind me why
WITH-SLOTS behaves as it does?
-rpg-
∂04-Feb-87 1415 Gregor.pa@Xerox.COM class-named
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Feb 87 14:12:38 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 04 FEB 87 12:57:54 PST
Date: 4 Feb 87 12:57 PST
From: Gregor.pa@Xerox.COM
Subject: class-named
To: Common-Lisp-Object-System@Sail.Stanford.edu
cc: Gregor.pa@Xerox.COM
Message-ID: <870204-125754-114@Xerox>
the function class-named is missing from the spec. It should be
documented something like this:
class-named <name> &optional (<errorp> t)
The first argument to class-named should be a symbol. class-named
returns the class-named by that symbol if there is one. If there is no
class-named by that symbol and the second argument is unsupplied or is
not nil, class-named signals an error. If there is no class-named by
that symbol, and the second argument is nil, class-named returns nil.
I don't believe anyone objects to the existence of this function.
∂04-Feb-87 1504 Gregor.pa@Xerox.COM my comments on 2/2/87 draft of functi
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Feb 87 15:02:19 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 04 FEB 87 14:13:52 PST
Date: 4 Feb 87 14:13 PST
From: Gregor.pa@Xerox.COM
Subject: my comments on 2/2/87 draft of functi
To: Common-Lisp-Object-System@Sail.Stanford.edu
cc: Gregor.pa@Xerox.COM
Message-ID: <870204-141352-1087@Xerox>
Here are a bunch of comments on the 2/2 draft of functi. Also scattered
in here for your reading pleaser are my proposals for how to solve some
other problems like:
- initialization
- setf generic function argument lists
- indentation convention for defclass
--
add-method (and remove-method)
still say that it accepts symbols or a list of (SETF <symbol>) as
argument. I proposed and Moon agreed that it should only accept generic
function objects as its first argument. In a separate message I will
mail out a proposal for ensure-generic-function which is needed as part
of this change. For the time being I suggest that
ensure-generic-function be added to functi to "hold a place for it".
--
call-next-method
(2nd paragragh under purpose, end of next to last sentence)
The phrase "otherwise it is the next most specific primary method" is
wrong. It should be something like "otherwise it is the effective
method which would have been called had there been no :around methods".
(1rst paragraph under remarks)
The last sentence would be more clear if it read:
Neither argument defaulting, nor the use of setq, nor rebinding the
variables with the
same names as parameters affects the values call-next-method passes to
the method it
calls.
--
change-class
(1rst para under purpose, 3rd sentence)
should say the class-changed generic-function is called.
I don't like the indenting of the defclass forms in the examples here.
I would like to see defclass dorms indented as follows.
If there are no slots and no options, it should be all on one line:
(defclass foo () ())
(defclass bar (foo) ())
If there are slots or options, the name and supers should be on the
first line, then the slot descriptions should be indented under the c in
defclass, then the options should be indented under the e in defclass.
This puts the slot-descriptions in a place that doesn't move when there
are supers, and makes a nice "line" between them and the options.
(defclass foo ()
((a 1)
(b 2)))
(defclass bar (foo)
((c 3)
(d 4))
(:accessor-prefix bar-))
(defclass baz (bar)
()
(:metaclass mumble))
--
class-of
last paragraph on the page (under remarks)
shouldn't this say that class-of returns a class at "least as specific"
as specified according to figure 1-2. The difference is that what is
written says that class-of will always return a class the user has heard
of, what I am suggesting is that class-of will always return a subclass
of a class the user has heard of.
--
defclass
(2nd para under purpose)
"that FUNCTIONS be automatically generated" should be "that METHODS
automatically BE DEFINED ON GENERIC-FUNCTIONS to .." or something like
it. This same mistake occurs later in the paragraph. It looks like
someone just lifted this from some defstruct documentation somewhere.
The 3rd (and last) paragraph under purpose wouldn't be needed if we
could figure out this type to class mapping better and explain it
better.
Under Syntax:
the abbreviation for having an initform with no other slot options
(<slot-name> <initform>) is missing.
the argument to accessor-prefix and friends is described as string or
symbol. Its always a symbol, its sometimes NIL.
Under arguments:
(2nd para) it doesn't say that the superclass-name arguments must name a
class of class standard-class. This may not be the right place to say
it, but I can't find this anywhere.
(3rd para) "there must not be any duplicate slot-names" Or else what?
Perhaps "If there are any duplicate slot-names an error is signalled"
would be better.
Under the description of class-options, the argument to :accessor-prefix
and friends is also listed as a string-or-symbol.
Under values:
I thought we decided all these DEF forms were going to return the object
they defined?
Under remarks:
(6th para after the 4 bullets), there is a sentence missing before the
last sentence. The last sentence reads "No other slot option may appear
more than once.." The missing sentence would say which slots options
could appear more than once.
--
defgeneric-options-setf (and defmethod-setf)
Let me say once again, that in order for the user to be able to add
methods to a setf-generic-function with add-method, we must document the
convention which defgeneric-options-setf and defmethod-setf use to pass
the new-value argument to the setf generic function. I believe the
convention we must use is that the new-valeu argument to setf becomes
the first argument to the generic function. Using this convention, the
user could write the following piece of code.
(defgeneric-options-setf foo (moving-obj) (new-foo))
(add-method (get-setf-generic-function 'foo)
(make-method :specializers (list (class-named 't)
(class-named 'plane))
:function #'(lambda (new-value plane) ..)))
Unless anyone objects to this convention or to documenting it, it should
be placed in the document either in concepts or under defmethod-setf or
defgeneric-options-setf or some combination and cross-referenced etc.
If someone needs help explaining this let me know.
--
get-method
The specializers argument needs to be changed to be a list of
class-objects or (QUOTE <datum>).
get-method should not error in the case where no such method exists.
get-method is the only way to see if such a method exists, it should
return nil if there isn't one. Once get-method is changed this way,
add-method and remove-method's error conditions are good.
--
invalid-method-error and method-combination-error
I still don't like having these as separate functions. Could we put a
note saying that if the condition system is adopted before this
proposal, these functions would be replaced by descriptions of the
appropriate condition to signal?
--
make-generic-function and make-method
I thought we had decided to remove this from the spec. I believe the
only thing holding that up is a decision about the initialization
protocol. Since nothing is happening with the initialization protocol,
I plan to write up a revised version of my Strawman, incorporating the
comments I have received from Moon and as Linda to put it in the spec.
Afterwards, I think we should replace make-generic-function and
make-method with descriptions of the appropriate arguments to pass to
make-instance to make a method a generic-function (and a class).
--
with-slots
The first paragraph under arguments should probably say the instance
form must evaluate to an object of class standard class. The
meta-object protocol chapter will describe how to extend with-slots to
work with instances with other meta-classes.
∂04-Feb-87 1718 Moon@STONY-BROOK.SCRC.Symbolics.COM More feedback from Symbolics reviewers
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 4 Feb 87 17:17:45 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 62496; Wed 4-Feb-87 20:16:52 EST
Date: Wed, 4 Feb 87 20:16 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: More feedback from Symbolics reviewers
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870204201632.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
In the current version of the document, CALL-NEXT-METHOD is documented
as a macro. That was a mistake; it should be a function. The document
should be updated. We'll do it next time we get the lock on the document,
unless someone else does it first, which would be perfectly okay with me.
The Remarks field of CALL-NEXT-METHOD should say that it can only be
called from the lexical scope of the body of a DEFMETHOD or DEFMETHOD-SETF.
The current documentation sort of implies this but doesn't say it explicitly.
In most implementations CALL-NEXT-METHOD will be defined with a FLET
that DEFMETHOD wraps around its body, rather than being a global function,
and maybe the Remarks field should mention this.
In the Possible Extensions field of CALL-NEXT-METHOD, the sentence that
discusses APPLY-NEXT-METHOD should be deleted. Regular APPLY can be used
now that it is a function.
Making it a function instead of a macro makes it slightly more difficult
for implementations to optimize it, but not significantly more difficult.
It makes the semantics simpler and more consistent with the rest of Lisp.
Does anyone object to these changes?
∂04-Feb-87 2012 Gregor.pa@Xerox.COM initialization protocol
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Feb 87 20:11:56 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 04 FEB 87 19:37:57 PST
Date: 4 Feb 87 19:37 PST
From: Gregor.pa@Xerox.COM
Subject: initialization protocol
To: Common-Lisp-Object-System@Sail.Stanford.edu
cc: Gregor.pa@Xerox.COM
Message-ID: <870204-193757-1495@Xerox>
Here is my proposed initialization protocol. It is based on the
one I sent out before. Like that protocol, the primary goals are
simplicity and flexibility. This proposal also includes some comments
about the conventions for use of this protocol.
There are two major changes in this protocol:
1.) there is a system-supplied initialize method which processes
the &rest argument to make-instance as plist of slot names
and values. This method initializes the slots of the instance
from the values in this plist, any slot for which no value
is specified in the plist is initialized from the default
value specified in the defclass form. This change provides
the user with access to the canned functionality of treating
the &rest argument to make-instance as a plist of slot-names
and values. It provides it in a way that Moon seems to like
in which the :initforms in the defclass are only evaluated
when no value for the slot is specified in the &rest argument
to make-instance.
2.) initialize take the &rest argument which was passed to
make-instance as a single argument rather than an &rest or
&key argument. This is the part of this protocol I am the
least attached to. If we want to change this so that
make-instance uses apply to call initialize I am amenable
to that. The reason I have done it this way is to avoid the
pain of always having to add:
(.. &rest options &key &allow-other-keys)
to initialize methods.
Here is some prototype code which implements this protocol. I am
using this code here because it is simple, and it makes it exactly
clear what happens when.
(defmethod make-instance ((class-name symbol) &rest options)
(apply #'make-instance (class-named class-name) options))
(defmethod make-instance ((class class) &rest options)
(let ((instance (make-instance-internal class)))
(initialize instance options)
instance))
(defmethod initialize ((o object) options)
(dolist (slot-name (all-slots (class-of o)))
(setf (slot-value o slot-name)
(let* ((getf-default (list nil))
(plist-value (getf options slot-name getf-default)))
(if (eq plist-value getf-default)
(evaluate-initform o slot-name)
plist-value)))))
The convention for the &rest argument to make-instance (which I will
call the init-plist but someone else is free to invent a better term) is
as follows:
It should be a true plist, the keys (odd-numbered elements of
the list) should be either:
slot-names, in which case the default initialize method (or
some user-defined initialize method will initialize the
slots from those values
keywords, a keyword implies that the initialize method is
going to do more "work" than just set the slot value (with
slot value). Things specified with keywords are often
compound values or values which don't map directly onto
slot values.
Here are some sample initialize methods. These show some standard stuff
people might want to do:
(defmethod initialize ((p plane) options)
(when options (error "Planes accept no init-plist")))
(defmethod initialize ((b boat) options)
(call-next-method) ;first do slot values
(when (cadr (memq options ':start)) ;then start if we should
(start boat)))
;;; note that the flet with apply used in this example is the downside
;;; of the decision to pass the options to initialize as one argument.
;;; as I said above, I think this is worth it.
(defmethod initialize ((m method) options)
;; We do hairy processing to set function specializers and
;; qualifiers in parallel. So we accept those as keywords.
(flet ((internal (&key function specializers qualifiers)
(setf (slot-value m 'function) function
(slot-value m 'specializers) specializers
(slot-value m 'qualifiers) qualifiers)
.. code to process the new values in parallel ..))
(apply #'internal options)))
;;; In this case, we want to process the options if there are any,
;;; but before we do so, we want to evaluate ALL the :initforms in
;;; the defclass and install them in the instance.
(defmethod initialize ((s ship) options)
(if (null options)
(call-next-method)
(progn
(initialize s ()) ;Go evaluate :initforms.
.. now process options ..)))
Some bugs (and answers) with my proposal:
B: The convention of using flet and apply is weird.
A: Its no so bad really, and its much better than having to say
&rest options &key &allow-other-keys all over
B: The default initialize method only signals an error if the
init-plist has an even number of elements. If the user
wants to implement complete error-checking of the init-plist
they have to do it themselves.
A: Right. Doing complete error checking of the init-plist
involves checking the values too, so if the user is going
to do that they will have no more code to write to check
the keys.
Please, speak now...
∂04-Feb-87 2107 Bobrow.pa@Xerox.COM Re: initializing class slots
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Feb 87 21:06:46 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 04 FEB 87 21:06:01 PST
Date: 4 Feb 87 21:05 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: initializing class slots
In-reply-to: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>'s
message of Wed, 4 Feb 87 12:05 EST
To: DLW@ALDERAAN.SCRC.Symbolics.COM
cc: Bobrow.pa@Xerox.COM, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870204-210601-1571@Xerox>
(defclass A () ((s :initform 1 :allocation :class)))
By the way, I could not find anything specific in the document
that says how initforms work for class slots. For example, exactly
when is the initform evaluated? At the time of the evaluating of
the containing defclass?
Yes and No. It is no because it is really at the time the class is
defined. Compiling a file with a defclass will expand the defclass into
something else, and that will evaluate at load time. But for ordinary
loading of files (or evaluating the form in a listener) the answer is
yes.
danny
∂04-Feb-87 2113 Bobrow.pa@Xerox.COM Re: Inheritance of Slot Options
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Feb 87 21:08:41 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 04 FEB 87 21:07:18 PST
Date: 4 Feb 87 21:07 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Inheritance of Slot Options
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 04 Feb 87
10:04 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870204-210718-1572@Xerox>
After a discussion with Linda, I believe your rules (that do not make
initform special) are reasonable in that they promote having all
descriptions of a slot in one place.
danny
∂04-Feb-87 2119 Bobrow.pa@Xerox.COM Re: Addendum to ``Inheritance of Slot Options''
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Feb 87 21:17:32 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 04 FEB 87 21:12:25 PST
Date: 4 Feb 87 21:12 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Addendum to ``Inheritance of Slot Options''
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 04 Feb 87
11:38 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870204-211225-1586@Xerox>
I forgot to mention in my last message that :allocation :none
should be flushed as well, because the current ``rules'' for it are
not as wonderful as someone might like. If we (democratically
construed) decide to keep :allocation :none, I think the rule I
proposed in the last message is adequate; possibly someone should
remind me why
As the last holdout for :none, I give in. I want to keep :dynamic however.
danny
∂04-Feb-87 2133 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Clarification
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 4 Feb 87 21:32:32 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 62566; Thu 5-Feb-87 00:23:17 EST
Date: Thu, 5 Feb 87 00:22 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Clarification
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870203-141235-2721@Xerox>
Message-ID: <870205002252.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 3 Feb 87 14:12 PST
From: Gregor.pa@Xerox.COM
Your "fair text" describes completely different inheritance rules. The
case in particular, as I outlined in my message on slot inheritance the
other day is:
(defclass foo ()
((a :allocation :class)))
(defclass bar (foo)
((a :initform ()))
Under the rules currently in the document, and the rules I mailed out
the other day:
instances of the class foo share a :class variable named a
instances of the class bar each have their own :instance variable a
Under the rules you propose its unclear what would happen. Perhaps
their would be two class variables, perhaps there would be one, its not
clear what would happen with :initform.
I agree with Gregor.
The rules described in the document should not be changed in substance.
I have only read them once, but they seem to match the rules which Danny
and I came up with and which I mailed out the other day.
They were intended to.
∂04-Feb-87 2134 RPG CL Types
To: common-lisp-object-system@SAIL.STANFORD.EDU
Not all Common Lisp programmers program in all Common Lisps. All classes
good for a Common Lisp might not be good for all Common Lisps. That is,
a lot of programmers program in exactly one Common Lisp, and their
code might not be portable, but it can be written portably.
-rpg-
∂04-Feb-87 2141 Moon@STONY-BROOK.SCRC.Symbolics.COM Various of Danny's Comments
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 4 Feb 87 21:36:06 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 62569; Thu 5-Feb-87 00:30:08 EST
Date: Thu, 5 Feb 87 00:29 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Various of Danny's Comments
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 2 Feb 87 19:45 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870205002948.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 02 Feb 87 1645 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Danny writes:
``I vote for (:accessor-prefix) as the right way to say use the
slot-names.''
To quote a famous computer scientist, ``ugh, bletch.''
I don't like this either, since it has nothing to do with prefixes. We
should say what we mean. How about :writable-instance-variables?
Excuse me, I mean :writeable-slots.
∂04-Feb-87 2146 RPG CALL-NEXT-METHOD
To: Common-lisp-object-system@SAIL.STANFORD.EDU
I think the fact that it isn't documented correctly is a slip-up.
I think we all agreed to this at one point, at least implicitly -
it was in your last define-method-combination proposal.
-rpg-
∂04-Feb-87 2149 Moon@STONY-BROOK.SCRC.Symbolics.COM Discussion at X3J13
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 4 Feb 87 21:45:21 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 62580; Thu 5-Feb-87 00:43:20 EST
Date: Thu, 5 Feb 87 00:43 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Discussion at X3J13
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870205004300.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
We should talk about how we're going to organize the discussion at
X3J13. I believe we have a whole day allocated to us. One way of
organizing it that I had in mind was for me to present the programmer
interface as it currently stands, for Danny to present the meta-object
protocol as it currently stands, for Dick to present the reasons why
this is the right thing for the broader Lisp community, not just for the
people like Xerox and Symbolics and TI with specialized Lisp machines,
and for anything left of the morning to be spent on questions and
answers directly related to the presentations. Then the next half day
would be spent either on more detailed Q&A if the meeting attendees seem
to have trouble understanding what's in the document, or else on
technical discussion of what changes they would like to propose, how to
finish the parts that we haven't finished yet, and "where do we go from
here" discussion. Does this sound good?
∂04-Feb-87 2218 RPG Clarification Clarification
To: common-lisp-object-system@SAIL.STANFORD.EDU
No one was trying to change anyone's rules about inheritance, though
in the end that happened. The problem was that LGD and I could not
figure out what the text in the document meant. Good intentions do
not make for good writing.
-rpg-
∂04-Feb-87 2226 Moon@STONY-BROOK.SCRC.Symbolics.COM call-next-method: More feedback from Symbolics reviewers
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 4 Feb 87 22:22:29 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 62592; Thu 5-Feb-87 01:01:52 EST
Date: Thu, 5 Feb 87 01:01 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: call-next-method: More feedback from Symbolics reviewers
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870204-212007-1602@Xerox>
Message-ID: <870205010132.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 4 Feb 87 21:20 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
In the current version of the document, CALL-NEXT-METHOD is
documented as a macro. That was a mistake; it should be a
function.
We need a proposal for the extension for call-next-method for changed
arguments. What is the problem with providing call-next-method with an
&rest argument, and if it is non-null, then argument checking is done on
those elements of the argument-list that have been used in the
discriminator-code.
No problem, that's what I had in mind. The only reason it's not in is
that someone wouldn't let me put it in because the proposal wasn't lean
enough. Maybe it's time to put it in now?
Does this argue for a macro implementation to allow
alternative expansions in the case where arguments are provided.
That was my idea at first, but it was firmly pointed out to me that
issues of optimization should be separated from issues of semantics.
Implementations can surely figure out how to make their compilers notice
whether arguments are provided or not, and generate different code.
One way is to declare the FLET function INLINE and constant-fold the
conditional inside the function that checks whether arguments were
supplied.
∂04-Feb-87 2142 Moon@STONY-BROOK.SCRC.Symbolics.COM CPL Varia
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 4 Feb 87 21:37:54 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 62576; Thu 5-Feb-87 00:35:56 EST
Date: Thu, 5 Feb 87 00:35 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: CPL Varia
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 1 Feb 87 17:10 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870205003536.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 01 Feb 87 1410 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Moon's writes:
``Oh, right, this only happens if you add the extension that the local
precedence order of a class can be a partial order rather than a total
order. We have that in Flavors, and it comes in handy, but I'm not
proposing to standardize on it at this time.''
I'm not sure what this means, but whether the local precedence order
is partial or total the leftmost siblings must come first.
No, the whole point of a partial local precedence order is that it is not
a total order. Therefore the classes mentioned in the direct superclass
list are not constrained to appear in the class precedence list in
the same order as they appear in the direct superclass list. Instead,
one specifies the local precedence order explicitly as a set of pairs
(before, after). (Well, actually, there is a little syntactic sugar,
but it's basically a set of ordered pairs.)
The example at the start of this message shows that
intuition isn't going to help much in all cases.
At this point I firmly believe that for any algorithm an example can be
constructed that can be plausibly argued to be unintuitive. I think the
important thing is for intuition to help in the cases that people expect
to be simple, not in all cases.
∂04-Feb-87 2141 Moon@STONY-BROOK.SCRC.Symbolics.COM Inheritance of Slot Options
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 4 Feb 87 21:34:23 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 62557; Thu 5-Feb-87 00:06:17 EST
Date: Thu, 5 Feb 87 00:05 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Inheritance of Slot Options
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 4 Feb 87 13:04 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870205000552.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 04 Feb 87 1004 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
I think the current spec suffers from excessive rules for the sake
of marginal functionality. I propose this slight modification:
We break what was slot options into two categories, slot descriptions
and slot options (in the BNF, what was ``slot options'' becomes ``slot
descriptor''). Slot options are the :accessor and :reader guys. Slot
descriptions are :initform, :allocation, and :type. The slot options
are as before. Slot description inherit like this:
Let CPL be the class precedence list for C. If C's defclass doesn't have a
slot descrption for a slot it is totally inherited from the next most
specific class in the CPL. If C's defclass has a slot description, it
totally shadows any other in CPL. When this latter case happens, some of
the aspects of the slot description might be defaulted. The defaulting is
as follows:
:initform is defaulted to unsupplied
:allocation is :instance
:type is T
The effective type of a slot is the AND of all types specified for it
in the CPL.
There are two differences between this and the previous rule (which I now,
unfortunately, understand). First, :initform acts differently - if you want
to change the :type or :allocation and keep the :initform, you have to mention
the :initform again. Second, it is an easier rule to understand and remember.
Third, when compiling a method you cannot assume anything about the types of
the slots, since a subclass could throw away your :type slot-option.
As far as I can tell this would make it impossible to use :type for anything,
certainly it seems to rule out the use you (Dick) mentioned for it when it
was first proposed.
I think it's counterproductive to have a complex set of rules to enforce
some intuition that doesn't pay its own way. A simpler but slightly inaccurate
model, where the inaccuracy to someone's intuition is unimportant, is
preferrable to a complex model that captures someone's epicycle.
These rules don't really seem any simpler to me. The concept of looking at
every slot-option in the class precedence list is no different from the concept
of looking at every method in the class precedence list; that concept has been
simplified out, but the concept of slot options and slot descriptions being
two different things has been added. No net gain.
In addition, I'm not happy about the idea that one cannot define an :accessor
for an inherited slot without clobbering its :initform. This seems just plain
wrong. It's a symptom either of your proposal not being right or of the whole
defclass syntax not being modularized properly.
∂04-Feb-87 2141 Bobrow.pa@Xerox.COM Re: More feedback from Symbolics reviewers
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Feb 87 21:34:41 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 04 FEB 87 21:20:07 PST
Date: 4 Feb 87 21:20 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: More feedback from Symbolics reviewers
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 4 Feb 87 20:16 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870204-212007-1602@Xerox>
In the current version of the document, CALL-NEXT-METHOD is
documented as a macro. That was a mistake; it should be a
function. The document should be updated. We'll do it next time
we get the lock on the document, unless someone else does it first,
which would be perfectly okay with me.
The Remarks field of CALL-NEXT-METHOD should say that it can
only be called from the lexical scope of the body of a DEFMETHOD or
DEFMETHOD-SETF. The current documentation sort of implies this but
doesn't say it explicitly. In most implementations CALL-NEXT-METHOD
will be defined with a FLET that DEFMETHOD wraps around its body,
rather than being a global function, and maybe the Remarks field
should mention this.
We need a proposal for the extension for call-next-method for changed
arguments. What is the problem with providing call-next-method with an
&rest argument, and if it is non-null, then argument checking is done on
those elements of the argument-list that have been used in the
discriminator-code. Does this argue for a macro implementation to allow
altrnative expansions in the case where arguments are provided.
danny
∂04-Feb-87 2352 RPG CPL Varia
To: common-lisp-object-system@SAIL.STANFORD.EDU
Now I understand about the partial ordering in Flavors. Interesting
idea.
In any event, Moon and I now agree on CPL, and, as you can all see, we
are engaged in strutting behavior. This might go on a little longer,
but most people enjoy watching peacocks spread their tail feathers.
-rpg-
∂04-Feb-87 2349 RPG Inheritance of Slots
To: common-lisp-object-system@SAIL.STANFORD.EDU
Moon writes:
``Third, when compiling a method you cannot assume anything about the types of
the slots, since a subclass could throw away your :type slot-option.''
I guess I didn't say it clearly enough. The effective type of a slot
is the AND (as in (AND T1 T2 ... Tn)) of the slots in the CPL. I thought
this was exactly what this meant:
``{\bf :type} is constrained to satisfy all of the type constraints given
by classes in the class precedence list. That is, if T1, T2 and so on are
the type constraints given by the class and all of its superclasses, the
value of the slot must satisfy {\bf (typep value '(and T1 T2 T3...)}.''
Didn't you (Moon) and Sonya write this?
Moon comments:
``No net gain.''
Before there were these categories of slot inheritance:
1. accessors and readers don't specially inherit
2. :allocation inherits some funny way
3. :initform inherits some other funny way
4. :type inherits by doing AND
Now we have:
1. accessors and readers as above
2. :allocation, :initform, and :type are totally
inherited or totally shadowed with simple defaults.
3. :type constrained to be AND.
Moon writes:
``In addition, I'm not happy about the idea that one cannot define an
:accessor for an inherited slot without clobbering its :initform.''
I thought my proposal said that if you mention slot options only
(:accessor, for example) normal inheritance happens. The simplified
rule is for slot descriptions only (:allocation, :type, :initform).
If you had :accessor only, the slot description stuff is totally
inherited - ``the right thing.'' If you mention a slot description,
all slot descriptions are shadowed. To be specific, the following
statement is true:
``one *can* define an :accessor for an inherited slot without clobbering
its :initform as long as :type and :allocation are not mentioned in the
defclass form.''
I think that the briarpatch of inheritance rules surrounding :allocation,
:type, and :initform are too complex.
-rpg-
∂05-Feb-87 0938 RPG X3J13 Discussion
To: common-lisp-object-system@SAIL.STANFORD.EDU
Moon's plan is reasonable, but I doubt we need to preach to the
converted - these people want to know technical details. I can
possibly moderate the discussion, but since I'm not running for
office and since there will be no babies to kiss, I can probably
skip the speech.
-rpg-
∂05-Feb-87 0955 DLW@ALDERAAN.SCRC.Symbolics.COM Re: initializing class slots
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 5 Feb 87 09:54:15 PST
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 47380; Thu 5-Feb-87 11:41:15 EST
Date: Thu, 5 Feb 87 11:38 EST
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Re: initializing class slots
To: Bobrow.pa@Xerox.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870204-210601-1571@Xerox>
Message-ID: <870205113817.8.DLW@CHICOPEE.SCRC.Symbolics.COM>
Line-fold: No
Date: 4 Feb 87 21:05 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
(defclass A () ((s :initform 1 :allocation :class)))
By the way, I could not find anything specific in the document
that says how initforms work for class slots. For example, exactly
when is the initform evaluated? At the time of the evaluating of
the containing defclass?
Yes and No. It is no because it is really at the time the class is
defined. Compiling a file with a defclass will expand the defclass into
something else, and that will evaluate at load time. But for ordinary
loading of files (or evaluating the form in a listener) the answer is
yes.
Actually, I'd take that as a "yes" answer. It's evaluated at the time
that the defclass is evaluated. Compiling a file causes the defclass to
be evaluated when the file is loaded. That is, defclass is (eval-when
(load eval) ...) by default, not (eval-when (compile load eval) ...).
So it's easy to explain.
∂05-Feb-87 1205 Bobrow.pa@Xerox.COM Re: Various of Danny's Comments
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Feb 87 11:46:14 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 FEB 87 11:21:16 PST
Date: 5 Feb 87 11:21 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Various of Danny's Comments
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 5 Feb 87 00:29 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870205-112116-2346@Xerox>
Danny writes:
``I vote for (:accessor-prefix) as the right way to say
use the slot-names.''
To quote a famous computer scientist, ``ugh, bletch.''
I don't like this either, since it has nothing to do with
prefixes. We should say what we mean. How about
:writable-instance-variables? Excuse me, I mean :writeable-slots.
This has everything to do with prefix. Its intention is to create from
the slot-names accessors (readers) with names constructed with no
prefix. Gregor tells me we argued this before and decided NIL was the
way to do it. So be it. But not a different class-option.
danny
∂05-Feb-87 1211 Lanning.pa@Xerox.COM Comments on Chapter 1
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Feb 87 11:47:17 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 FEB 87 11:25:13 PST
Date: 5 Feb 87 11:25 PST
Sender: Lanning.pa@Xerox.COM
From: Stan Lanning <Lanning.pa@Xerox.COM>
Subject: Comments on Chapter 1
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870205-112513-2354@Xerox>
Some comments on the Jan 23 draft of Chapter 1, Programmer Interface
Concepts. My apologies if there is a newer draft that has these fixed.
Page 1-6, section "The Structure of Instances", paragraph one states:
"The definition of the class specifies the structure of instances of the
class. The slots define the structure of the instance."
This seems contradictory to me. Perhaps the point is that the class
specifies the slots, and the slots define the structure instances.
Page 1-9, section "Inheritance of defclass Options"
The options are given here for the first time. It would be nice if they
had been mentioned before, perhaps with a brief description of their
intended function.
Page 1-15, section "Computing the Class Precedence List"
Sorry, the class lattice is not a lattice (in the mathematician's sense
of the word). For example, consider the following network:
T
/ \
A B
|\ /|
| X | ;; X is not a class, just two lines crossing
|/ \|
C D
\ /
NIL
The set {A, B} has no least upper bound, so the ordering isn't a
lattice. The most you can say is that the ordering is an acyclic
directed graph.
Also, "we assume they are consistent and that R is a partial ordering"
isn't right. You mean that the trasitive closure of R is a partial
ordering. Perhaps R should be defined to be the transitive closure, if
Rl and Rp are consistent?
Page 1-18, section "Introduction to Methods", states:
"If a defmethod form is evaluated and a method object corresponding to
the given parameter specializers already exists, the new definition
replaces the old."
How does this relate to qualified methods? Surely a (defmethod :before
...) doesn't replace an unqualified defmethod.
Page 1-24, section "Standard Method Combination" states:
"An error is signalled if call-next-method is used and there is no
appliciable primary method to call."
Is there going to be a (remaining-method-p) function? Or are you
counting on catching the error?
That's all for now.
----- smL
∂05-Feb-87 1227 Masinter.pa@Xerox.COM call-next-method is not a function
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Feb 87 12:23:44 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 05 FEB 87 12:03:37 PST
Date: 5 Feb 87 12:05 PST
From: Masinter.pa@Xerox.COM
Subject: call-next-method is not a function
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870205-120337-2399@Xerox>
It is wrong to say that call-next-method "is a function", because that
terminology is used exclusively in CLtL to mean that the symbol has a
global function definition with the given interpretation.
I think that careful wording is called for.
What would happen in the following
(defmethod test ((a wozzle)) #'call-next-method)
(defmethod caller ((a wombat) fn) (funcall fn))
(caller (make-wombat) (test (make-wozzle)))
would it call the next method of test, or the next method of caller?
∂05-Feb-87 1312 RPG Stan's Comments
To: common-lisp-object-system@SAIL.STANFORD.EDU
Stan has some good comments:
He writes:
``"The definition of the class specifies the structure of instances of the
class. The slots define the structure of the instance."
This seems contradictory to me. Perhaps the point is that the class
specifies the slots, and the slots define the structure instances.''
The two sentences on which he comments are not contradictory, only poorly
written. The language construct that serves to define the class
*specifies* the structure. The slots are the structure that is specified -
that is, they *define* it. The distinction is between the words `specify'
and `define,' the first being in a linguistic category the second being in
an operational category.
He's right it's bad wording because his quick reading did not result in
comprehension.
Stan mentions that the ``lattice'' isn't. I suppose we thought that the
rules for well-defined class structures would prevent situations like the
one he mentions, but they don't. I suppose I had hoped for an upper
semi-lattice, but it isn't in the cards. DAG it will probably be.
All the wording regarding orderings and their generators have long since been
made consistent. Though his comments are valuable, we generally have not
distributed the document of the date he mentions, but I guess a public file
is a public file.
-rpg-
∂05-Feb-87 1321 RPG Functions
To: common-lisp-object-system@SAIL.STANFORD.EDU
Larry writes:
``It is wrong to say that call-next-method "is a function", because that
terminology is used exclusively in CLtL to mean that the symbol has a
global function definition with the given interpretation.''
Larry's right about this, but this wording might be a little misleading.
He is contrasting the phrase ``is a function'' with ``is a macro'' and
``is a special form.'' In our document, we mention that this, that, or the
other thing is a function or a generic function.
Of course, Common Lisp does state that there are global names and local
names for functions, so one could have functions that are stored in
no function cell.
CALL-NEXT-METHOD is a function in the local-name sense in that it is
only an accessible function within method combination defining macros.
There should be some other phrase to describe this, I suppose.
-rpg-
∂05-Feb-87 2100 Moon@STONY-BROOK.SCRC.Symbolics.COM call-next-method is not a function
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 5 Feb 87 20:55:35 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 63741; Thu 5-Feb-87 23:30:21 EST
Date: Thu, 5 Feb 87 23:30 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: call-next-method is not a function
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870205-120337-2399@Xerox>
Message-ID: <870205233020.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 5 Feb 87 12:05 PST
From: Masinter.pa@Xerox.COM
It is wrong to say that call-next-method "is a function", because that
terminology is used exclusively in CLtL to mean that the symbol has a
global function definition with the given interpretation.
I think that careful wording is called for.
Good point.
What would happen in the following
(defmethod test ((a wozzle)) #'call-next-method)
(defmethod caller ((a wombat) fn) (funcall fn))
(caller (make-wombat) (test (make-wozzle)))
would it call the next method of test, or the next method of caller?
Of test.
∂06-Feb-87 0901 Gregor.pa@Xerox.COM Re: Functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Feb 87 09:00:29 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 06 FEB 87 08:51:20 PST
Date: 6 Feb 87 08:51 PST
From: Gregor.pa@Xerox.COM
Subject: Re: Functions
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 05 Feb 87
13:21 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870206-085120-3357@Xerox>
Doesn't this mean that we can say:
"within the body of a defmethod form, call-next-method is a
lexically bound function which ..."
∂06-Feb-87 1240 Gregor.pa@Xerox.COM ensure-generic-function
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Feb 87 12:38:01 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 06 FEB 87 12:14:43 PST
Date: 6 Feb 87 12:14 PST
From: Gregor.pa@Xerox.COM
Subject: ensure-generic-function
To: Common-Lisp-Object-System@Sail.stanford.edu
cc: Gregor.pa@Xerox.COM
Message-ID: <870206-121443-3684@Xerox>
Try this for ensure-generic-function:
ensure-generic-function <symbol>
&key (<generic-function-class>
(class-named 'standard-generic-function))
(make-exisiting-function-default-p nil)
If symbol is fboundp to a generic-function of the same class as
<generic-function-class> then this function does nothing.
If symbol is fboundp to a generic-function of some other class, the
generic-function class changing protocol is followed, see chapter 3.
If symbol not foundp a generic function of generic-function-class is
created and put in symbol's function cell.
If symbol is boundp to a function, and make-exisiting-function-default-p
is not nil, a generic-function is created, put in the function cell, a
default method is added to the generic-function and the symbol's
previous function cell value is used as the function for the default
method.
If symbol is fboundp to a function and make-exisiting-function-default-p
is nil an error is signalled.
If symbol names a macro or a special form, an error is signalled.
Feel free to change the names of the arguments. Note that this is a
function not a generic-function.
∂06-Feb-87 1350 Masinter.pa@Xerox.COM Re: call-next-method is not a function
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Feb 87 13:39:12 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 06 FEB 87 13:33:21 PST
Date: 6 Feb 87 13:34 PST
From: Masinter.pa@Xerox.COM
Subject: Re: call-next-method is not a function
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 5 Feb 87 23:30 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870206-133321-3786@Xerox>
Perhaps it is unavoidable, but the possible indefinite extent of the
call-next-method function also exposes another issue, which is whether
identity of the "next method" is closed over, or dynamic.
In the same example, given
(defclass wozzle (nozzle))
(defmethod test ((a wozzle)) #'call-next-method)
(defmethod test ((a nozzle)) "Nozzle tester")
(defvar *nozzle-tester* (test (make-wozzle)))
(defclass big-nozzle (nozzle))
(defclass wozzle (big-nozzle)) ; redefines wozzle
(defmethod test ((a big-nozzle)) "Big nozzle tester")
; whew...
(funcall *nozzle-tester*)
Does this get "Nozzle tester" or "Big nozzle tester"?
The issue is "what's closed over" in the call-next-method. Clearly it
has to close over the identity of the arguments. (All of the arguments.)
Its less clear whether it can somehow cache the identity of the classes
of the arguments, the class of the next argument, or any other
information which was used in the computation of this method. Its also
fairly sticky about what happens if this method gets removed from the
hierarchy.
Maybe its ok to leave this unstated, but it seems bothersome.
∂06-Feb-87 1350 Masinter.pa@Xerox.COM Re: Functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Feb 87 13:38:48 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 06 FEB 87 13:00:33 PST
Date: 6 Feb 87 13:01 PST
From: Masinter.pa@Xerox.COM
Subject: Re: Functions
In-reply-to: Gregor.pa's message of 6 Feb 87 08:51 PST
To: Gregor.pa@Xerox.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870206-130033-3754@Xerox>
The problem, I imagine, is that the manual format used so far requires
documented items to say something like [function] or [macro] in the
right margin, and neither is entirely appropriate.
∂06-Feb-87 1703 Bobrow.pa@Xerox.COM List of generic functions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Feb 87 16:58:52 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 06 FEB 87 16:53:46 PST
Date: 6 Feb 87 16:53 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: List of generic functions
To: Common-Lisp-Object-System@Sail.stanford.edu
cc: Bobrow.pa@Xerox.COM
Message-ID: <870206-165346-4066@Xerox>
The following is a list of the generic functions (and argument names)
that are in the metaobject protocol or are part of the extended
programming interface. I don't know how to distinguish these two. Some
of them have been been described in the first two chapters of the CLOS
document.
A description of what these generic functions do is coming later today.
But it is much longer.
The notation below uses (setf <generic-fn-name>) to indicate the setf
generic function that corresponds to <generic-fn-name>. The argument
shown for the setf function is only the new-value argument. The names
of the arguments are an attempt to give some clue as to the types of the
arguments.
**Class Access Generic Functions
class-direct-supers class
(setf class-direct-supers) list-of-classes
direct-subclasses class
class-precedence-list class
direct-slots class
(setf class-direct-slots) slot-descriptions
all-slots class
generic-functions class
class-prototype class
**Slot-Description Access Generic Functions
slotd-name slot-description
slotd-initform standard-slot-description
(setf slotd-initform) form
slotd-allocation standard-slot-description
slotd-type standard-slot-description
**Inherited Class Structure
compute-class-precedence-list class &optional possible-supers
compatible-super-p class possible-direct-super
collect-slot-descriptions class &key
:direct-supers :direct-slotds
compute-effective-slot-description class same-named-slotds
update-class class &key :direct-supers :direct-slots
add-direct-subclass class subclass
remove-direct-subclass class subclass
supers-changed class old-supers old-slots
&optional top-flag &rest rest-args
slots-changed class old-slots
&optional top-flag &rest rest-args
update-method-inheritance class old-supers
**Obsolete Classes
make-class-obsolete class
has-instances-p class
change-class instance new-class
class-changed previous current
** Parsing defclass form
expand-defclass metaclass-prototype defclass-form
check-defclass-form metaclass-prototype slot-list class-options
add-named-class metaclass-prototype
name super-list slot-list class-options
class-for-redefinition metaclass-prototype
old-class-with-name &rest other-information
make-slot-description metaclass-prototype slot-description-list
** Class names
class-named name &optional no-error-flag
(setf class-named) class
class-name class
(setf class-name) name
class-named-from-metaclass metaclass-prototype
name &key :no-error-flag :compile-time-hash-table
(setf class-named-from-metaclass) class
** Slot access
slot-value-using-class class instance-of-that-class slot-name
&optional value-if-slot-missing
slot-missing instance slot-name
(setf slot-value-using-class) new-value
slot-missing-for-setf instance slot-name new-value
slot-exists-p instance slot-name &optional allocation
all-slot-names instance &optional allocation
add-dynamic-slot instance slot-name new-value
remove-dynamic-slot instance slot-name
get-dynamic-slot-value instance slot-name &optional default-value
** Compiling Slot Access
optimize-slot-value class-of-object form
optimize-setf-slot-value class-of-object form
** Type Relations
classp instance class
subclassp class1 class2
** Method Acess Functions
method-generic-function method
method-parameter-specializers method
method-function method
(setf method-function) function
method-qualifiers method
** Generic Function Access generic functions
gf-methods generic-function
gf-discriminator-code
gf-argument-list generic-function
(setf gf-argument-list) lambda-list
gf-argument-precedence-order generic-function
(setf gf-argument-precedence-order) list
gf-method-class generic-function
(setf gf-method-class) class
gf-method-combination generic-function
(setf gf-method-combination) method-combination-option
gf-declarations generic-function
(setf gf-declarations) declaration-list
** Changing Generic Functions
ensure-generic-function symbol
&key :generic-function-class :make-exisiting-function-default-p
add-method generic-function method
remove-method generic-function method
get-method generic-function parameter-specializers
generic-function-changed gf &optional hints
get-setf-generic-function symbol
** Changing code of generic functions
compute-discriminator-code generic-function
compute-effective-method generic-function combination-type
applicable-methods &optional parameters
find-applicable-methods generic-function
argument-list &optional sorted-flag
method-equal method1 method2
method-more-specific generic-function
method1 method2 argument-list
** Making new storage types for metaclasses
define-metaclass name size class-of-code
meta-allocate-instance meta-name &optional size
meta-slot-value meta-name thing position
meta-set-slot-value meta-name thing position new-value
make-memory-block size
danny
∂06-Feb-87 1830 Bobrow.pa@Xerox.COM LONG MESSAGE -- Draft of meta-object protocol
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Feb 87 18:25:48 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 06 FEB 87 18:16:11 PST
Date: 6 Feb 87 18:15 PST
From: Bobrow.pa@Xerox.COM
Subject: LONG MESSAGE -- Draft of meta-object protocol
To: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <870206-181611-4193@Xerox>
Meta-object Protocol (DRAFT 6 Feb 87)
The meta-object protocol is based upon a set of objects that are defined
in the system. The following is a public view of these classes.
Implementations are free to have addtional slots, or simulate slots
using the accessors that are defined. For all slots specified, there is
a reader with the prefix specified. For some slots setf methods are
also defined as described below. The notation (setf
<generic-function-name>) is used to refer to such methods.
There are four pairs of classes described: class, standard-class,
slot-description, standard-slot-description, method, standard-method,
generic-function and standard-generic-function. The first of each pair
represents what is thought of as the minimal or most abstract
functionality to be defined in CLOS. The second, with prefix standard-,
are the ones described in chapters 1 and 2.
All these classes are required to be instances of standard-class. All
instances of standard class (these are all classes)inherit from
standard-object which defines a small set of default behaviors. This
class is effectively defined by:
(defclass standard-object (t)())
Behaviors for standard-object include methods for describe, print-object
and initialize as described in the concepts chapter.
There are two major sections, one dealing with the classes and
slot-descriptions, the second with methods and generic-functions. Both
start with descriptions of the classes and then describe other methods
specialized to the classes, organized by their use in the metaobject
protocol. Methods that are described in the function chapter are
mentioned but not described.
1. Classes and Slot Descriptions
Classes are used for two distinct purposes: to describe the structure of
a set of objects, and as a parameter specializer for the definition of
methods. The description of the structure uses a set of objects that
are instances of slot-descriptions. Classes specify some direct
slot-descriptions, and inherit others from their super-classes. We
first show the structure of class, and standard class, and then the
classes for slot-descriptions.
1.1 Class and standard-class
(defclass class (standard-object)
(direct-supers
direct-subclasses
class-precedence-list)
(:reader-prefix class-))
(defclass standard-class (class)
(direct-slots
all-slots
generic-functions
prototype)
(:reader-prefix class-))
[[Initial values for these slots are all NIL]]
direct-supers is a list of class objects. If it is changed, then the
updating protocol described below is followed.
There is a setf generic function for class-direct-supers.
(setf class-direct-supers) on class causes the direct-supers slot to get
updated, and calls supers-changed. See supers-changed.
direct-subclasses is a list of classes. It is the inverse of the links
from direct-supers. If x is in the direct-supers of y, then y is in the
direct-subclasses of x. See add-direct-subclass,
remove-direct-subclass.
There is no setf generic function for class-direct-subclasses.
class-precedence-list is a list of classes. It is computed from
direct-supers. It is computed (just) before the first instance of this
class is created, or when any method is defined on this class or any
subclass. It is maintained whenever supers of this class or any super
class change. See compute-class-precedence-list, compatible-super-p,
supers-changed.
There is no setf generic function for class-class-precedence-list.
direct-slots is a list of slot-description objects. If it is changed,
then the updating protocol described in section 1.4.
There is a setf generic function for class-direct-slots.
(setf class-direct-slots) on class signals an error.
(setf class-direct-slots) on standard-class causes the class to get
updated. See slots-changed and section 1.4.
all-slots is a list of slot-description objects. It is computed from
direct-slots of all the classes on class-precedence-list. It is
computed (just) before the first instance of this class is created, or
with-slots is expanded for any method on this class or subclass. It is
maintained if the supers or slots of the class or any of its supers are
changed. See collect-slot-descriptions,
compute-effective-slot-description, supers-changed, slots-changed.
There is no setf generic function for class-all-slots.
generic-functions is a list of generic-function objects that have a
method defined using this class as a parameter specializer. A generic
function appears on this list only once no matter how many relevant
methods it contains. It is kept on a class as a cache to allow access
to methods that depend on the class definition. This allows updating of
methods when classes change. It also provides a hook for browsers in an
environment. It is maintined by add-method.
There is no setf generic function for class-generic-functions.
prototype contains an instance of this class. It is created the first
time the accessor class-prototype is used. The prototype is not
guaranteed to have any slots filled in. It is to be used as an argument
to allow access to methods specialized to the class that don't use the
contents of an instance of the class. This is used extensively in the
paarsing of the defclass form, for example. In general, it allows a
specialized method to be invoked without having to create a new instance
of the class each time.
There is no setf generic function for class-prototype.
1.2 Slot-description and standard-slot-description
(defclass slot-description (standard-object)
(name)
(:reader-prefix slotd-))
(defclass standard-slot-description (slot-description)
(initform
allocation
type)
(:reader-prefix slotd-))
name is a symbol that CLtL allows to be used as a variable. An instance
of any class that contains a slot-description with this name will have
access to a slot of this name. See concepts document.
There is no setf generic function for slotd-name.
initform is a lisp form.
There is a setf generic function for slotd-initform.
(setf slotd-initform) sets the value of initform and calls
slots-changed.
allocation is one of :instance, :class, :dynamic.
There is no setf generic function for slotd-allocation
See the concepts chapter to see how these values are used for
standard-class.
type is a Common Lisp type descriptor
There is no setf generic function for slotd-type
class-value is the storage for a value in a class.
There is a setf function for slotd-class-value
(setf slotd-class-value) sets the value.
1.3 Creation of classes
Classes are instances of metaclasses. Hence they can be created by the
ordinary make-instance protocol. The initalization of a class allows
allows two slot-names to be given:
direct-slots with value a list of slot-description objects
direct-supers with value a list of classes (or names of classes) These
names are changed to the classes they refer to (using
class-named-for-metaclass) as the first step in
compute-class-precedence-list. An error is signalled if a class is not
defined with that name at that time.
In addition, at the start of the computation of class-precedence-list, a
compatibility check is made to determine whether the class (of this
metaclass) can inherit from the specifed direct-super-classes using:.
compatible-super-p class possible-direct-super
class is the one to get the new possible-direct-super class. If this
method returns NIL an error is signalled. The default method for
compatible-super-p allows use of possible-direct-super only if the
metaclasses of class and possible-direct-super are the same.
compute-class-precedence-list class
&optional (direct-supers (class-direct-supers class))
This computes a total order extracted from the direct-supers of the
class. The optional argument allows the environment to compute what the
class-precedence-list would be if the direct-supers were those provided.
See concepts chapter for the behavior of compute-class-precedence-list
for class.
Once the class-precedence list is computed, the set of all
slot-descriptions for the class can be computed.
collect-slot-descriptions class
&key (direct-supers (class-direct-supers class))
(direct-slotds (class-direct-slots class))
This generic-function computes a list of slot-descriptions interpreted
as a set. The importance of the word set is that the order of the
slot-descriptions is not guaranteed to be used by the implementation to
build instance structure.
No two slot-descriptions in the set can have the same name. The set of
slot-descriptions is computed using the method
compute-effective-slot-description, called once for each name in the
union of all the slot-descriptions of all the classes in the
class-precedence list. An implementation is free to add additional
slot-descriptions.
The optional arguments possible-direct-supers and possible-direct-slots
are available so that the environment can ask what the set of slots
would be if those were used instead of the values in the current slots.
compute-effective-slot-description class same-named-slotds
The argument same-named-slotds is a list of slot-descriptions in
most-specific-first order specified by the class-precedence-list. The
behavior of this method for the standard-slot-description is found in
the concepts chapter.
1.4 Updating classes
A standard-class once defined can be updated to have different
direct-slots and direct-supers
update-class class &key :direct-supers :direct-slots
where direct-supers is list of classes and direct-slots is a list of
slot-descriptions. It allows only a single updating pass when both
direct-supers and direct-slots are changing.
To preserve the backlinks from supers to subclasses, the following
generic functions are provided. supers-changed calls these.
add-direct-subclass class subclass
adds subclass to direct-subclasses if it is not present.
remove-direct-subclass class subclass
removes subclass from direct-subclasses of class if it is present. It
signals an error if subclass was not in the list.
If any changes are made to supers, the class-precedence-list of this
class and its subclasses may have changed. The set of slot-descriptions
of this class and subclasses might have changed. To allow updating of
these slots, and any other cached information in a particular
implementation, the protocol calls the recursive generic function:
supers-changed class old-supers old-slots
&optional top-flag &rest rest-args
When this method is invoked, it is assumed that class-direct-supers and
class-direct-slots will return their new values. The old values are
provided to facilitate making incremental changes. The contract of the
generic function is to update any cached information about supers and
slots in class, and any of its subclasses. supers-changed is called
recursively on all the subclasses of the class that is changed. The
variable top-flag, which is T only on the initial call from updating
methods, allows specialized methods to take specific actions for the
class that has changed directly. The rest-args are provided so that
extra information can be passed down by specializations, if desired.
The supers-changed method for standard-class updates the
class-precedence-list, and the list of all-slots using
compute-class-precedence-list, and collect-slot-descriptions. It also
makes obsolete any class that has a different shape, that is has a
different number or organization for slots. See below for a further
description of obsolete classes. supers-changed is called by
(setf class-direct-supers) and by update-class.
A similar protocol support updating if only the set of slot-descriptions
provided have changed using the generic function slots-changed
slots-changed class old-slots
&optional top-flag &rest rest-args
It is assumed any updating to direct-slots has already been done. The
old-slots are provided to facilitate updating. The contract of the
generic function is to update any cached information about slots in
class, and any of its subclasses. The variable top-flag, which is T
only on the initial call, allows specialized methods to take specific
actions for the class which directly changed. The rest-args are
provided so that extra information can be passed down by
specializations, if desired.
The method for standard-class updates the list of all-slots using
collect-slot-descriptions. It also makes obsolete any class that has a
different shape, that is has a different number or organization for
slots. See below for a further description of obsolete classes.
In order to support caching in generic functions, when a class is
changed, the following protocol is supported
update-method-inheritance class old-supers
In standard-class this causes recomputation of effective methods for all
the generic functions on this class and any subclass.
1.5 Obsolete Classes
If the effect of updating the class is to change the shape of instances
that would be produced by this class, then instances produced according
to the former description are now "obsolete"; that is they no longer
conform to the current description in the class by this name. When a
class must be made obsolete, a protocol informs the class:
make-class-obsolete class
To determine if a class needs to be made obsolete, it is a useful
optimization to know if any instances of this class have ever been made.
has-instances-p class
is a predicate that returns NIL if it knows no instances have ever been
made.
For standard-class, make-class-obsolete ensures that old instances are
now instances of an obsolete-class that knows about the old structure,
and about the new class description. The next time any instance of this
obsolete class is used either as an argument to slot-value, or as a
specialized argument for a method,
(change-class instance updated-class)
is called to change it to conform to the new class definition. See
concepts chapter for further discussion
1.6 Expanding defclass forms
This protocol is defined to allow users to extend the use of defclass in
some limited ways. For this purpose, we define the abstract syntax of
defclass as follows:
(defclass name (super-name*)
((slot-name {slot-prop slot-prop-value}*)*)
{(class-option-keyword . class-option-args)}*)
That is, slots can have an arbitrary property list following the name,
and all class-options are lists with a keyword. The only way to specify
the metaclass used by defclass is by using the :metaclass class-option.
The metaclass option is used to get a prtotype of the metaclass for use
by the generic functions specified below
The types of extensions we visualize are ones that would allow
additional slot-properties and class options interpreted by the
metaclass.
expand-defclass metaclass-prototype defclass-form
uses the :metaclass option to obtain a prototype of the metaclass, and
expands the defclass form.
check-defclass-form metaclass-prototype slot-list
class-options
signals an error if there are any slot-properties or class-options that
are not recognized.
add-named-class metaclass-prototype
name super-list slot-list class-options
creates the appropriate class, doing the conversion from a list of names
to a list of super-classes, converting the slot-list to a list of
slot-descriptions of the appropriate kind. The defclass expansion
contains an (add-named-class ...) form. The other forms in the
expansion of a defclass form are expressions to creating the accessor,
reader and constructor methods specified in the defclass form.
add-named-class checks if these is currently a class defined with the
same name. If so, it checks to see if it is acceptable to update that
class using the generic function:
class-for-redefinition metaclass-prototype old-class-with-name
&rest other-information
class-for-redefinition signals an error if the class cannot be
redefined, else, or returns a class that is to be updated (this might be
a new class or the old one). On class, class-for-redefinition always
signals an error. standard-class, it updates the class and supports
obsolete instances.
make-slot-description metaclass-prototype
slot-description-list
creates the appropriate kind of slot-description object for class,
filling it in from slot-description-list
This is how extensions to the slot-properties can be added without
breaking defclass.
compute-super-from-name metaclass-prototype name
is used to obtain a class from a name. It can use class-named or in a
compile-time environment may want to be shadowed to find a special class
object or definition.
1.7 Class names
The association of a name with a class is supported by the metaclass.
Not all classes need have names. The basic lookup function is:
class-named-from-metaclass metaclass-prototype name
&key :no-error-flag :compile-time-hash-table
This returns the class with that name, or signals an error if none. If
no-error-flag=T then returns NIL if none. If compile-time-hash-table is
given then it is used for looking up names, and for setting them. This
allows a sompiler to interface with this metaclass specific name lookup.
There is a setf generic function defined for class-named-from-metaclass.
(setf class-named-from-metaclass)
signals an error if name is already in use for another class. It
no-error-flag is T, then this is a noop.
Additional support for instances of class is provided by
class-named name &optional no-error-flag
class-named is defined in terms of class-named-from-metaclass.
If a class has a name, then it can be found using:
class-name class &optional unnamed-value
Returns the name of a class, if it has one, or returns unnamed-value.
There is a setf generic function defined for class-name.
(setf class-name) name
We do not need a class-name-using-metaclass since class-name is already
specialized to the class.
If new-name is NIL, then class will have no name afterwards. If
new-name is the name of another class, then an error is signalled. If
class has another name, then class will be first made unnamed, then then
given the new name. It is noop if class already has that name.
1.7 Instance Slot Access
The function slot-value is defined to use:
slot-value-using-class class instance-of-that-class slot-name
&optional value-if-slot-missing
This method on the metaclass that knows the representation of the
instance, and returns the value. It calls slot-missing if a slot by
this name is not accessible from this instance. If
value-if-slot-missing is provided, this value returned instead of
calling slot-missing.
slot-missing instance slot-name
is called if no slot with slot-name is accessible in instance. The
method for slot-missing on standard-class just signals an error
There is a setf generic function for slot-value-using-class.
(setf slot-value-using-class) sets the value of the specified slot. It
calls slot-missing-for-setf if a slot by this name is not accessible
from this instance. If value-if-slot-missing is provided in the
slot-value form, this value is returned instead of calling
slot-missing-for-setf
slot-missing-for-setf instance slot-name new-value
The method on class for slot-missing-for-setf signals an error.
slot-exists-p instance slot-name &optional allocation
is a predicate that returns true if there is a slot with name slot-name
accessible from instance. If allocation is given, then returns true if
it has the given allocation. Returns NIL otherwise
all-slot-names instance &optional allocation
returns the list of all slot-names accessible within this instance,
limiting it to slots with a particular allocation if that argument is
given.
add-dynamic-slot instance slot-name new-value
adds to instance a dynamic slot with value new-value. Signals an error
if slot-name is already a slot accessible from instance, and not a
dynamic slot. If it is a dynamic slot then just changes the value.
remove-dynamic-slot instance slot-name
removes the dynamic slot from the instance. Signals an error if such a
slot does not exist on the instance.
dynamic-slot-value instance slot-name &optional default-value
gets the value from the dynamic slot. Signals an error if slot is not a
dynamic slot, or returns default-value it is provided.
(setf dynamic-slot-value) new-value
sets the value of the dynamic slot. Signals an error if slot is not a
dynamic slot, or returns default-value it is provided.
1.8 Optimizing Slot Access at Compilation
To provide users a hook to optimize access to slots in compiled code,
the protocol provides
optimize-slot-value class-for-var form
This returns a specialized form for compilation, or original form if it
can do nothing with the form. It can check in the method about the
parameter-specializer for any arguments in the form. form look like:
(slot-value <var-name> '<slot-name>)
optimize-setf-slot-value class-for-var form
returns a specialized form for compilation, or original form. form must
be of the form (setf (slot-value <var-name> '<slot-name>...)...)
1.9 Relationships among classes and instances
The class system extends the type system. There are methods that
correspond to typep and subtypep
classp instance class
Returns T if (class-of instance) is a subclass of class, that is, if
(subclassp (class-of instance) class).
subclassp class1 class2
returns T if class2 is an element of the class precedence list of
class1, that is, if class2 is class1 or any of its superclasses.
[[?? As an alternative, we could extend typep and subtypep directly to
allow class arguments where they now have type-specifier arguments]]
2. Methods and Generic Functions
2.1 Method Structure
(defclass method (object)
(generic-function
parameter-specializers
function)
(:reader-prefix method-))
(defclass standard-method (method)
(qualifiers)
(:reader-prefix method-))
generic-function is NIL or the generic-function of which this method is
a part.
There is no setf generic function for method-generic-function.
parameter-specializers is a list of elements interpeted by
compute-discriminator-code to determine if this method is applicable for
a particular set of arguments. For standard-method, this list consists
of class objects or lists of the form (QUOTE individual). See concepts
chapter.
There is no setf generic function for method-parameter-specializers.
function is a function that generic-function will call if the
discriminator-code selects this method as the appropriate effective
method. This method function can be applied directly to the same
argument list to the generic-function, provided the arguments match
their parameter-specializers.
There is a setf generic function for method-function.
(setf method-function) fn
signals an error if the fn can not be determined to have a lambda list
congruent with that of the generic function. (setf method-function)
calls generic-function-changed.
qualifiers is a list of non-nil atoms.
There is no setf generic function for method-qualifiers.
2.2 Generic Function Structure
(defclass generic-function (object)
(methods
discriminator-code)
(:reader-prefix gf-))
(defclass standard-generic-function (generic-function)
(argument-list
argument-precedence-order
method-class
method-combination
declarations)
(:reader-prefix gf-))
methods is a list of method objects.
There is no setf generic function for gf-methods
discriminator-code is a function that actually does the discrimination
when the a generic-function is called. Implementations are free to make
special classes of generic-function objects that are recognized by the
interpreter, and for which the discrimination code is done in the
interpreter.
There is no setf generic function for gf-discriminator-code.
For the following, see also the discussion in the function and concepts
chapters.
argument-list is an ordinary CL lambda-list with no aux variables.
There is a setf generic function for gf-argument-list.
If there are any methods on the generic function, it signals an error if
the argument list is not congruent to those of the methods.
argument-precedence-order specifies the order that is to be used in
computing precedence of methods. It is a permutation of the required
arguments of argument-list. It is used by compute-discriminator-code to
determine the order of applicability of methods.
There is a setf method for gf-argument-precedence-order.
If it is used, it checks that the new value is a permutation of the
required arguments of argument-list, or signals an error. If
argument-precedence-order is different than it was before,
compute-discriminator-code is called to update the gf-function.
method-combination is a list whose first element (car) is the
combination type and the rest (cdr) is a list of parameters for
method-combination.
There is a setf generic-function for gf-method-combination with a method
defined for standard-generic-function. If it is used, then
compute-discriminator-code is called to update the gf-function.
method-class is a class. It will be used as the class for methods
defined with defmethod on this generic-function.
gf-method-class has a setf-method.
declarations are those provided in def-generic-options. It is used by
compute-discriminator-code.
gf-declarations has a setf method.
2.3 Creating Methods and Generic Functions
Instances of methods and generic functions are made using make-instance.
The initialize method for method supports slot-names of
parameter-specializers, argument-list and function. The initialize
method for generic-function supports properties for all of its slots
except discriminator-code.
ensure-generic-function symbol &key class make-fn-be-default-p
is documented in the concepts and function chapter.
2.4 Manipulating generic-functions and methods
add-method generic-function method
remove-method generic-function method
get-method generic-function parameter-specializers
generic-function-changed gf &optional hints
this is called by add-method remove-method and (setf method-function)
get-setf-generic-function symbol
These are documented in the concepts and function chapter.
2.5 Building Code for Generic Functions
The code used by a generic function is computed by the following method.
All callers of this method know how to install that code.
compute-discriminator-code generic-function
This method returns a function, or some object recognizable to the
implementation dependent code that installs this function in the
generic-function object.
The usual way for people to effect what code is generated is throguh
method combination, and its define-method-combination interface. This
interface defines a method on the generic-function
compute-effective-method.
As part of the code, if there is no applicable method for a
generic-function, the generic function should call the method
no-matching-method generic-function arglist
The default method for this generic function signals an error.
compute-effective-method
generic-function
combination-type
applicable-methods
&optional parameters
This should return a form that is used for the body of an effective
method composed from the set of applicable methods. It can use
make-method-call. See concepts chapter. The contract between
compute-discriminator-code and compute-effective-method says that it
must be called for all significantly different sets of applicable
methods that can arise from a set of arguments.
If the user wants to build code using compute-discriminator-code, the
following methods may prove useful.
find-applicable-methods generic-function
argument-list &optional sorted-flag
returns a list of methods on generic-function that are applicable to the
arguments given. If sorted-flag the list is sorted most-specific-first.
method-equal method1 method2
tests whether two methods of the same generic-function have the same
specializers and qualifiers.
method-more-specific generic-function
method1 method2 argument-list
Returns T if method1 is more specific than method2 with respect to the
argument list.
3.0 Defining New Storage Metaclasses
In order to define new mechanisms for storing instances, there must be
some system dependent code. The interface to that code is:
define-metaclass name size class-of-code
This function creates associated with name
1) a mechanism for allocating structures of this kind
The structure should be of the size specified. If size is NIL, then
the allocation routine will expect a parameter indicating the desired
size.
2) a mechanism for recognizing when a structure of this type is asked
for its class. For such structures, the function (or macro) specified
by class-of-code will return the code.
A new class must also be defined using the same name. In its
make-instance method it can use:
meta-allocate-instance meta-name &optional size
meta-slot-value meta-name thing position
meta-set-slot-value meta-name thing position new-value
As a mechanism for storing slots, the user should have accessible a
function (macro)
make-memory-block size
and accessor
memory-block-ref block size
In PCL these are just calls to make-vector but something better is
probably needed.
∂06-Feb-87 2030 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: call-next-method is not a function
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 Feb 87 20:29:09 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 64725; Fri 6-Feb-87 23:27:51 EST
Date: Fri, 6 Feb 87 23:27 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: call-next-method is not a function
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870206-133321-3786@Xerox>
Message-ID: <870206232754.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 6 Feb 87 13:34 PST
From: Masinter.pa@Xerox.COM
Perhaps it is unavoidable, but the possible indefinite extent of the
call-next-method function also exposes another issue, which is whether
identity of the "next method" is closed over, or dynamic.
In the same example, given
(defclass wozzle (nozzle))
(defmethod test ((a wozzle)) #'call-next-method)
(defmethod test ((a nozzle)) "Nozzle tester")
(defvar *nozzle-tester* (test (make-wozzle)))
(defclass big-nozzle (nozzle))
(defclass wozzle (big-nozzle)) ; redefines wozzle
(defmethod test ((a big-nozzle)) "Big nozzle tester")
; whew...
(funcall *nozzle-tester*)
Does this get "Nozzle tester" or "Big nozzle tester"?
The issue is "what's closed over" in the call-next-method.
In my trial implementation I did back in September, it closes over everything
and the answer is "Nozzle tester". But if you read the Remarks field of
change-class (in the 31 Jan version), this situation is already explicitly
undefined (the "first semantic difficulty") if we merely extend "the execution
of a method" to include the lifetime of any call-next-method closures it creates.
So let's just add a sentence there mentioning call-next-method closures. This
includes not only #'call-next-method, also #'(lambda .... (call-next-method) ...),
thus the problem was not introduced by changing call-next-method from a macro
to a function.
A related issue, which I think should be explicitly defined, is to make clear
that
(defmethod ...
(dotimes (i 100)
(call-next-method)))
calls the same method 100 times. It does not call the 100 next most specific
methods (erring if there are fewer than 100).
∂06-Feb-87 2124 Moon@STONY-BROOK.SCRC.Symbolics.COM Gregor's comments on 2/2/87 draft of functi
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 Feb 87 21:23:43 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 64740; Sat 7-Feb-87 00:22:23 EST
Date: Sat, 7 Feb 87 00:22 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Gregor's comments on 2/2/87 draft of functi
To: Common-Lisp-Object-System@Sail.Stanford.edu
In-Reply-To: <870204-141352-1087@Xerox>
Message-ID: <870207002216.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 4 Feb 87 14:13 PST
From: Gregor.pa@Xerox.COM
Here are a bunch of comments on the 2/2 draft of functi.
The last draft I've seen is 1/31; what changed?
--
add-method (and remove-method)
still say that it accepts symbols or a list of (SETF <symbol>) as
argument. I proposed and Moon agreed that it should only accept generic
function objects as its first argument. In a separate message I will
mail out a proposal for ensure-generic-function which is needed as part
of this change. For the time being I suggest that
ensure-generic-function be added to functi to "hold a place for it".
In general I agree with that. There might be some details to settle.
I think the discussion happened after we finished editing the document,
which is why it didn't get reflected. There may not be quite time to
finish this before Dick's stated deadline of Sunday night.
--
call-next-method
(2nd paragragh under purpose, end of next to last sentence)
The phrase "otherwise it is the next most specific primary method" is
wrong. It should be something like "otherwise it is the effective
method which would have been called had there been no :around methods".
Right, looks like an editing mistake since it's the same text as in the
next sentence.
(1rst paragraph under remarks)
The last sentence would be more clear if it read:
Neither argument defaulting, nor the use of setq, nor rebinding the
variables with the
same names as parameters affects the values call-next-method passes to
the method it
calls.
Whatever.
--
change-class
(1rst para under purpose, 3rd sentence)
should say the class-changed generic-function is called.
I agree.
I don't like the indenting of the defclass forms in the examples here.
I would like to see defclass dorms indented as follows.
If there are no slots and no options, it should be all on one line:
(defclass foo () ())
(defclass bar (foo) ())
If there are slots or options, the name and supers should be on the
first line, then the slot descriptions should be indented under the c in
defclass, then the options should be indented under the e in defclass.
That's okay with me. I guess it's time we spent the 5 minutes it takes to
make our editor know about defclass and enforce those indentation rules.
--
class-of
last paragraph on the page (under remarks)
shouldn't this say that class-of returns a class at "least as specific"
as specified according to figure 1-2. The difference is that what is
written says that class-of will always return a class the user has heard
of, what I am suggesting is that class-of will always return a subclass
of a class the user has heard of.
In general I agree. I think your proposed wording is still confusing.
I would rephrase it (assuming "meta-instance of" as a dual of
"meta-class of" is defined elsewhere):
If the object is a meta-instance of STANDARD-TYPE-CLASS, the class
returned may be a subclass of one of the classes listed in Figure 1-2.
I'm not sure the phrase "most specific class" really means anything, I
would avoid it.
--
defclass
(2nd para under purpose)
"that FUNCTIONS be automatically generated" should be "that METHODS
automatically BE DEFINED ON GENERIC-FUNCTIONS to .." or something like
it. This same mistake occurs later in the paragraph. It looks like
someone just lifted this from some defstruct documentation somewhere.
Agreed.
The 3rd (and last) paragraph under purpose wouldn't be needed if we
could figure out this type to class mapping better and explain it
better.
I disagree. This is the class to type mapping, not the type to class
mapping; the description here is about as specific as could be; and I
think defclass is a good place to mention it. Probably it should be
mentioned in the Concepts chapter too.
Under Syntax:
the abbreviation for having an initform with no other slot options
(<slot-name> <initform>) is missing.
Agreed. Does anyone think this should not be put back?
the argument to accessor-prefix and friends is described as string or
symbol. Its always a symbol, its sometimes NIL.
Agreed that string should go away. I think the special-casing of NIL
should go away too, but Danny is still resisting.
Under arguments:
(2nd para) it doesn't say that the superclass-name arguments must name a
class of class standard-class. This may not be the right place to say
it, but I can't find this anywhere.
I don't think it should be explained in terms of standard-class. I think
the explanation should be that if a class and one of its superclasses are
of different metaclasses, whether this is valid depends on the particular
two metaclasses and is controlled by the meta-class protocol. Further
discussion should be in the meta-objects chapter. The special case of a
standard class and a standard type class is mentioned on the last page of
the Concepts chapter.
(3rd para) "there must not be any duplicate slot-names" Or else what?
Perhaps "If there are any duplicate slot-names an error is signalled"
would be better.
Yes, although that language can get rather stilted when discussing macros,
where the errors are signalled at compile time rather than run time.
Under the description of class-options, the argument to :accessor-prefix
and friends is also listed as a string-or-symbol.
Under values:
I thought we decided all these DEF forms were going to return the object
they defined?
This seems to have been changed back and forth several times. I'm happy
with all of them returning the object if that's okay with everyone else.
Under remarks:
(6th para after the 4 bullets), there is a sentence missing before the
last sentence. The last sentence reads "No other slot option may appear
more than once.." The missing sentence would say which slots options
could appear more than once.
Editing error. The last sentence of that paragraph belongs two paragraphs
earlier ("It is valid to specify...").
--
defgeneric-options-setf (and defmethod-setf)
Let me say once again, that in order for the user to be able to add
methods to a setf-generic-function with add-method, we must document the
convention which defgeneric-options-setf and defmethod-setf use to pass
the new-value argument to the setf generic function. I believe the
convention we must use is that the new-valeu argument to setf becomes
the first argument to the generic function.
Wouldn't it be better to ask the generic function what its convention is?
Probably a generic function on a generic function and two lambda-lists that
returns one lambda-list.
This seems to be just one of several things we have to solve or clarify if
we expect the add-method level to be taken seriously.
--
get-method
The specializers argument needs to be changed to be a list of
class-objects or (QUOTE <datum>).
As I've said several times, this isn't right because it doesn't extend well
to discriminating on optional and keyword arguments. I agree that class
objects rather than class names are wanted, now that we have clarified that
redefining a class modifies the existing class object rather than creating
a new one. I don't agree with the format as a simple list.
get-method should not error in the case where no such method exists.
get-method is the only way to see if such a method exists, it should
return nil if there isn't one. Once get-method is changed this way,
add-method and remove-method's error conditions are good.
Give it an optional error-p argument, I think.
--
invalid-method-error and method-combination-error
I still don't like having these as separate functions. Could we put a
note saying that if the condition system is adopted before this
proposal, these functions would be replaced by descriptions of the
appropriate condition to signal?
I don't agree with this. I believe in abstractions for signalling
conditions rather than signalling them directly. I can spend time
writing a detailed explanation if the motherhood statement that
abstractions are good, and a few minutes thought about proceeding,
aren't enough to convince you.
--
make-generic-function and make-method
I thought we had decided to remove this from the spec. I believe the
only thing holding that up is a decision about the initialization
protocol. Since nothing is happening with the initialization protocol,
I plan to write up a revised version of my Strawman, incorporating the
comments I have received from Moon and as Linda to put it in the spec.
Afterwards, I think we should replace make-generic-function and
make-method with descriptions of the appropriate arguments to pass to
make-instance to make a method a generic-function (and a class).
Agreed tentatively.
--
with-slots
The first paragraph under arguments should probably say the instance
form must evaluate to an object of class standard class.
I assume you made a typo here and you meant to say that the document
should -not- say this. with-slots should work for anything. Of course
if the class has no slots it will be a no-op, but it shouldn't blow out.
The
meta-object protocol chapter will describe how to extend with-slots to
work with instances with other meta-classes.
That's why with-slots should work for anything.
∂06-Feb-87 2137 Moon@STONY-BROOK.SCRC.Symbolics.COM Inheritance of Slots
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 Feb 87 21:36:43 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 64749; Sat 7-Feb-87 00:34:58 EST
Date: Sat, 7 Feb 87 00:35 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Inheritance of Slots
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 5 Feb 87 02:49 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870207003502.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 04 Feb 87 2349 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Sorry about the 2-day delay in response, I've been real busy with other things
this week.
Moon writes:
``Third, when compiling a method you cannot assume anything about the types of
the slots, since a subclass could throw away your :type slot-option.''
I guess I didn't say it clearly enough. The effective type of a slot
is the AND (as in (AND T1 T2 ... Tn)) of the slots in the CPL. I thought
this was exactly what this meant:
``{\bf :type} is constrained to satisfy all of the type constraints given
by classes in the class precedence list. That is, if T1, T2 and so on are
the type constraints given by the class and all of its superclasses, the
value of the slot must satisfy {\bf (typep value '(and T1 T2 T3...)}.''
Didn't you (Moon) and Sonya write this?
Yes. I was commenting on your apparent proposal to change that rule so
that the effective type of a slot depended on -only- the most specific
slot-description, when you said "If C's defclass has a slot description,
it totally shadows any other in CPL." If you weren't really proposing
to make that change, then there is no problem.
Moon comments:
``No net gain.''
Before there were these categories of slot inheritance:
1. accessors and readers don't specially inherit
2. :allocation inherits some funny way
No, :allocation doesn't inherit.
3. :initform inherits some other funny way
No, the most specific :initform is used.
4. :type inherits by doing AND
Now we have:
1. accessors and readers as above
2. :allocation, :initform, and :type are totally
inherited or totally shadowed with simple defaults.
3. :type constrained to be AND.
The only change is one cannot specify any slot options without
clobbering the :initform. Nothing about :allocation or :type has
changed. I really think it would be a bad idea to change :initform
inheritance. Please leave it the way it is.
...I thought my proposal said that if you mention slot options only
(:accessor, for example) normal inheritance happens.
I didn't get that from reading your proposal. If I had I would have
barfed, because that's a really strange rule. In the slot description
list of defclass, (foo :allocation :instance) would mean something
different from (foo), because one prevents inheritance of :initform
and the other doesn't. I would have real difficulty agreeing that
that is simple!
The simplified
rule is for slot descriptions only (:allocation, :type, :initform).
If you had :accessor only, the slot description stuff is totally
inherited - ``the right thing.'' If you mention a slot description,
all slot descriptions are shadowed. To be specific, the following
statement is true:
...I think that the briarpatch of inheritance rules surrounding :allocation,
:type, and :initform are too complex.
I don't disagree, but I think your suggestion doesn't make it simpler.
At the risk of repeating myself, flushing :allocation and :type would
make it a lot simpler. So would forbidding two classes in a given class
precedence list from describing the same slot. Short of that, I don't
see any way to make it simpler.
∂06-Feb-87 2218 RPG Semantic difficulties
To: common-lisp-object-system@SAIL.STANFORD.EDU
Better read that prose quickly, because it is among the 2 or 3 sections
regarded as too pathetic to make it into the final version in a shape very
much resembling what's there now. It is replaced with a more terse
comment.
Possibly defining CALL-NEXT-METHOD to have dynamic extent within
a generic function invocation along with Moon's clarification of
100 Iterations of Call-Next-Methoditude would do the trick?
-rpg-
∂06-Feb-87 2301 RPG Inheritance of Slots
To: common-lisp-object-system@SAIL.STANFORD.EDU
Moon writes:
``No, :allocation doesn't inherit.''
Moon wrote in CONCEPTS:
``{\bf :allocation} comes from the most specific slot description in
the class precedence list---if it
does not explicitly specify {\bf :allocation}, the default is
{\bf :allocation} {\bf :instance}.''
What is the ``most specific slot description''? Is it the one closest
to the front? Is there some intrinsic specificity of a slot description?
What is ``it''? Is ``it'' the most specific slot description? Is ``it''
the class precedence list? Is this not some sort of inheritance?
Moon wrote in CONCEPTS:
``{\bf :initform} comes from the most specific slot description
that explicitly specifies {\bf :initform}. ''
So what does this do:
(defclass c1 () ((s :allocation :class :initform 99)))
(defclass c2 (c1)((s :initform 22)))
Is S an :instance in instances of C2 ? Is it a :class in C2? Is it shared
with the one in C1? Do we reinitialize S?
``{\bf :type} is constrained to satisfy all of the type constraints given
by classes in the class precedence list.''
What does ``constrained'' mean? Is there enforcement? Is it the same way that
slots in Defstructs have :type declarations? If so, this doesn't say it.
Steele's working is much better.
Well, maybe Moon's right, we should leave it as it is so that the readers of
the document can have fun guessing what this mess means. LGD and I sure had
fun for a day doing exactly this. All we were doing with our suggestions was
to propose something that someone could understand along with a description
of it that was understandable.
The point of a specification is to spell out the details in such a way
that they are precise, unambiguous, and clearly stated. This specification
does not do that.
-rpg-
∂09-Feb-87 0802 Bobrow.pa@Xerox.COM Re: Stan's Comments
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Feb 87 08:02:22 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 09 FEB 87 08:02:09 PST
Date: 9 Feb 87 08:01 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Stan's Comments
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 05 Feb 87
13:12 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870209-080209-5490@Xerox>
rules for well-defined class structures would prevent
situations like the one he mentions, but they don't. I suppose I
had hoped for an upper semi-lattice, but it isn't in the cards. DAG
it will probably be.
Since this is so, it means that we do not need a class named NIL to
close the bottom. This allows (CLASS-NAME class) ->NIL to mean no name.
danny
∂09-Feb-87 0814 Bobrow.pa@Xerox.COM Re: Discussion at X3J13
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Feb 87 08:14:46 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 09 FEB 87 08:06:09 PST
Date: 9 Feb 87 08:06 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Discussion at X3J13
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 5 Feb 87 00:43 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870209-080609-5502@Xerox>
We should talk about how we're going to organize the discussion
at X3J13. I believe we have a whole day allocated to us. One way
of organizing it that I had in mind was for me to present the
programmer interface as it currently stands, for Danny to present
the meta-object protocol as it currently stands.
This is OK with me. I do want the best draft we can have of what I sent
out on Friday to go out with the other two chapters. I recognize that
this has not been argued about and hence may change in a significant
ways before it is adopted, but I think people should have some chance to
see what is being referred to before I talk about it. As I said in my
earlier message, most of it is the extended programmers tools for
working with the the object system.
danny
∂09-Feb-87 1046 Gregor.pa@Xerox.COM Re: Inheritance of Slots
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Feb 87 10:46:11 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 09 FEB 87 10:27:50 PST
Date: 9 Feb 87 10:24 PST
From: Gregor.pa@Xerox.COM
Subject: Re: Inheritance of Slots
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 06 Feb 87
23:01 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870209-102750-5712@Xerox>
So what does this do:
(defclass c1 () ((s :allocation :class :initform 99)))
(defclass c2 (c1)((s :initform 22)))
Is S an :instance in instances of C2 ? Is it a :class in C2? Is it
shared
with the one in C1? Do we reinitialize S?
I can't understand why you found this so confusing. Before you started
hacking what Moon wrote, I sent out a message which included a different
explanation of these rules and exactly included this example.
I find the inheritance mechanism Moon was describing quite simple (I
agree the description could be improved) all you have to do is get the
slot descriptions in class precedence list order, default them according
to the appropriate rule for each option and then pick the most specific
*supplied* value for each option. The only thing even remotely complex
is that one of the options (:initform) defaults to *unsupplied*.
I also don't like the new rules you have proposed.
∂09-Feb-87 1841 MOON@AI.AI.MIT.EDU X3J13 version of document
Received: from AI.AI.MIT.EDU by SAIL.STANFORD.EDU with TCP; 9 Feb 87 18:41:12 PST
Date: Mon, 9 Feb 87 21:41:30 EST
From: "David A. Moon" <MOON@AI.AI.MIT.EDU>
Subject: X3J13 version of document
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <151649.870209.MOON@AI.AI.MIT.EDU>
The concep.tex and functi.tex files on SU-AI have not changed at all since
the versions I put there on 31 Jan. Since it is now after midnight on Feb
8, I assume this means that the versions that will be mailed out are
identically those. If what's being mailed is stored someplace else than
[cls,lsp] on su-ai, please let me know in time to read them before they are
printed up. I do not want something being mailed out with my name on it
that I have not seen (not that I expect any surprises). I'll try to phone
Lucid Tuesday afternoon to check on the status of the files.
My comments on recent discussion about inheritance and so forth will be
mailed out when it stops snowing and my connection to the Arpanet comes
back..
∂09-Feb-87 2044 RPG Document
To: common-lisp-object-system@SAIL.STANFORD.EDU
Sounds like Moon made a mistake in accepting my deadlines, which
carefully outlined the steps leading up to the mailing. He should have
requested that work stop a week earlier.
As mentioned in my previous messge on the topic, the documents are now in
the maw of my grammarians who are making sure they aren't completely
embarrassing. I expect the documents to pop out by friday, just in time to
be mailed.
Nothing regarding semantics has been changed except for those things
which were so poorly written that the most reasonable re-write changed
them. Inheritance of slots is as it was, though I rewrote it to
be a little less confusing.
As expected, the document was badly inconsistent throughout, because
everyone who had their hands on it decided to introduce their own
personal jargon with little thought to how it went together.
The title page now lists authors separately from contributors.
Because time is short, I'll remove Moon's and Sonya's names from the authors
list, but leave them as contributors. Later, when they approve or whatever,
and the document is in final form we can put them back.
-rpg-
∂10-Feb-87 0245 RPG State of the world
To: common-lisp-object-system@SAIL.STANFORD.EDU
Here is what Linda and I have been doing to the specification.
1. Settling on terminology. This mostly involves selecting one
out of several different terminologies inserted into the spec
by different people, where the terms refer to the same thing.
2. Making the organization right. In several places material that
belongs in FUNCTIONS ended up in CONCEPTS and vice versa. Sometimes
material was repeated. These were rationalized and pointers back and
forth were placed where appropriate.
3. Clarifying terminology. This mostly happened in places where people
had inserted good terminology without definition or comment on its
use. A good example is ``primary method,'' which is used intuitively
in some places and precisely in others. We put in an explanation of
the use of the term in CONCEPTS. The explanation says that a primary
method is used to refer to a method with an intended role depending on
the method combination type. In standard method combination it means
a certain thing (precisely) as it does when you use the short form (though it
means something slightly different). This way the reader is not jolted
upon reading in standard method combination that a primary method is
precisely an unqualified method while under the short form he'll read
that some qualified methods are primary. (And without the explanation,
a reader could spend 15 minutes going back and forth among the
various apparent definitions of it).
4. Rationalizing where objects versus names of objects are to be used,
particularly in parameter specializers where one thing is meant in
specialized lambda-lists and another in parameter specializers of a method
object (one needs names and the other needs objects).
5. Incorporating the latest, most final comments of Gregor and Moon.
I'm not sure we've done this completely well, but we did all the comments
through Feb 6.
6. Re-writing sections that were very hard to understand. The worst
part was redefining classes and the change-class protocol, which Moon
put in during the last round. After a number of sessions on the phone
with Danny and Gregor and after a face-to-face with them, I think we
finally have it down reasonably. This re-write impacted number 4 above.
I think that Moon's change-class protocol, though a little obscure, is
now understandable, which means it has some hope of gaining approval
in March.
7. Correcting grammar. There were many grammatical and punctuation
mistakes made here and there. Some seem to be typos and oversights.
Correcting these takes sharp, fresh eyes.
8. Formatting was regularized and BNF's were scrutinized.
9. Typesetting bugs were and aesthetics improved.
We are still 1/2 day away from being done with this cleanup. The magnitude
of work required to achieve 1 through 7 was much greater than we thought, which
is why the documents are not now on [cls,lsp]. I'm afraid that people are not
going to get much of a chance, if any, to read the document before it goes out.
But the document can be superceded at the March meeting, and we didn't
intentionally change any content, even in the parts we don't like.
I think the document is complex enough that the folks who will try to read
it for March deserve as much time as possible to grind through it.
Mostly because redundancies were removed, the document will be approximately
82 pages long: 26 pages for CONCEPTS and 56 for FUNCTIONS.
-rpg-
∂10-Feb-87 0936 Moon@STONY-BROOK.SCRC.Symbolics.COM Inheritance of Slots
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 10 Feb 87 09:34:29 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 67053; Tue 10-Feb-87 12:32:58 EST
Date: Tue, 10 Feb 87 12:32 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Inheritance of Slots
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 7 Feb 87 02:01 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870210123253.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 06 Feb 87 2301 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Moon writes:
``No, :allocation doesn't inherit.''
Moon wrote in CONCEPTS:
``{\bf :allocation} comes from the most specific slot description in
the class precedence list---if it
does not explicitly specify {\bf :allocation}, the default is
{\bf :allocation} {\bf :instance}.''
What is the ``most specific slot description''? Is it the one closest
to the front? Is there some intrinsic specificity of a slot description?
I thought this was clear from context, in the three paragraphs before the
one you quoted. Re-reading them, it would be clearer to some readers if it
said explicitly "The slot descriptions are ordered according to the order
of classes in the class precedence list." instead of only implying that.
What is ``it''? Is ``it'' the most specific slot description? Is ``it''
the class precedence list? Is this not some sort of inheritance?
"It" is the most specific slot description; slot descriptions are the only
things that specify {\bf :allocation}. This would be better written as two
sentences with no pronouns.
Dick, the problem here is that in the piece of mail you quoted I used the
word "inherit" in a different sense from the way it's used in the document.
I think the 31 Jan version of the document is consistent in its use of
inherit, and has it that :allocation does inherit. When I said :allocation
does not inherit, I meant that only the most specific slot description for
a given slot affects :allocation. When the document says that :allocation
does inherit, it means that the most specific slot description controls
:allocation, even if that slot description is attached to a superclass of
the class whose slots are being discussed. So I don't think we are disagreeing
about anything here.
Moon wrote in CONCEPTS:
``{\bf :initform} comes from the most specific slot description
that explicitly specifies {\bf :initform}. ''
So what does this do:
(defclass c1 () ((s :allocation :class :initform 99)))
(defclass c2 (c1)((s :initform 22)))
Is S an :instance in instances of C2 ?
Of course. :allocation comes from the most specific slot description.
Is it a :class in C2?
No, since it's :instance.
Is it shared with the one in C1?
Of course not.
Do we reinitialize S?
I don't know what this means. My guess is you're referring to the weird
thing that would happen if we had different inheritance rules for :allocation,
so that C2's class definition referred to a :class slot of C1.
A weirdo case you were perhaps thinking of is
(defclass c1 () ((s :allocation :class :initform 99)))
(defclass c2 (c1)((s)))
Here the instance slot named S in a C2 is initialized to 99.
I propose that this not a problem.
``{\bf :type} is constrained to satisfy all of the type constraints given
by classes in the class precedence list.''
What does ``constrained'' mean? Is there enforcement? Is it the same way that
slots in Defstructs have :type declarations? If so, this doesn't say it.
Steele's working is much better.
I don't know what it means. We just put it in the document based on what
was said in the mail. Here is all the mail I was able to find on the
subject.
Date: 17 Nov 86 14:33 PST
Sender: Bobrow.pa@Xerox.COM
:type type-expression
should be allowed as it is in DEFSTRUCT. No requirements on its use
should be in the standard.
Date: Fri, 21 Nov 86 23:08 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
I don't see what use this could be, but I don't see how it could hurt,
other than by making the language larger. Let's go ahead and put it in.
Date: 22 Nov 86 1048 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Sometimes a compiler will be able to optimize things a little given some
information like this. It might not be that the storage or its direct
handling will improve or change, but, perhaps, some other operation can be
slightly improved - such a being able to emit the machine addition
instruction with only overflow checking - when the slot, directly, is
involved in an arithmetic expression.
Date: 5 Jan 87 11:07 PST
Sender: Bobrow.pa@Xerox.COM
:type is inherited, but we do not specify what the system does with it.
An open question is whether inheritance here should be a union
operation, or if the more specific type must always be a subtype of the
inherited one.
If "Steele's wording" refers to p.310 of CLtL, that's probably saying the
same thing, although it's a little vague too. The analogy to type declaration
of a variable is valuable and should be used in our document.
Well, maybe Moon's right, we should leave it as it is so that the readers of
the document can have fun guessing what this mess means. LGD and I sure had
fun for a day doing exactly this. All we were doing with our suggestions was
to propose something that someone could understand along with a description
of it that was understandable.
The point of a specification is to spell out the details in such a way
that they are precise, unambiguous, and clearly stated. This specification
does not do that.
I will say only that I am glad that the process of review is resulting in
an improved document.
∂10-Feb-87 0943 Moon@STONY-BROOK.SCRC.Symbolics.COM Document
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 10 Feb 87 09:41:41 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 67062; Tue 10-Feb-87 12:40:11 EST
Date: Tue, 10 Feb 87 12:40 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Document
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 9 Feb 87 23:44 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>,
The message of 10 Feb 87 05:45 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870210124014.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 09 Feb 87 2044 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Sounds like Moon made a mistake in accepting my deadlines, which
carefully outlined the steps leading up to the mailing. He should have
requested that work stop a week earlier.
All I want is an open process. I hadn't expected from your deadlines
message that the final revision would be done in secret. I'm willing to
blame this on the poor quality of Arpanet communications. Your second
message listing what you've done is helpful; thanks.
The title page now lists authors separately from contributors.
Because time is short, I'll remove Moon's and Sonya's names from the authors
list, but leave them as contributors. Later, when they approve or whatever,
and the document is in final form we can put them back.
I don't think this really helps, so why don't you not bother to change it.
Date: 10 Feb 87 0245 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Here is what Linda and I have been doing to the specification....
5. Incorporating the latest, most final comments of Gregor and Moon.
I'm not sure we've done this completely well, but we did all the comments
through Feb 6.
I'd like to see what happened here, since I thought some of the issues weren't
resolved yet. Or maybe you only incorporated the ones that have been resolved.
∂10-Feb-87 0946 Moon@STONY-BROOK.SCRC.Symbolics.COM Semantic difficulties
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 10 Feb 87 09:46:39 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 67071; Tue 10-Feb-87 12:45:10 EST
Date: Tue, 10 Feb 87 12:45 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Semantic difficulties
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 7 Feb 87 01:18 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870210124511.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 06 Feb 87 2218 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Possibly defining CALL-NEXT-METHOD to have dynamic extent within
a generic function invocation along with Moon's clarification of
100 Iterations of Call-Next-Methoditude would do the trick?
I don't think so. I don't see why it should have dynamic extent
rather than indefinite extent like all other closures. Furthermore,
changing the class in the middle of a method can make its valid
extent end even before dynamic extent ends.
∂10-Feb-87 1106 Bobrow.pa@Xerox.COM Re: Inheritance of Slots
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Feb 87 11:04:19 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 10 FEB 87 10:40:34 PST
Date: 10 Feb 87 10:38 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Inheritance of Slots
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 10 Feb 87 12:32 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870210-104034-6948@Xerox>
I read the current document last night and was appalled at the
complexity of the rules that were used to explain the inheritance of the
characterisics of slot-descriptions. I also realized that accessors
and readers MUST be inherited. A new method need not be built for every
class if the implementation guarantees that the method inherited still
works. But whenever there is a change of the :allocation
characteristic, every accessor and reader in the inheritance chain must
have a new method created for it.
danny
∂10-Feb-87 1211 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Inheritance of Slots
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 10 Feb 87 12:11:49 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 67300; Tue 10-Feb-87 15:10:43 EST
Date: Tue, 10 Feb 87 15:10 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Inheritance of Slots
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870210-104034-6948@Xerox>
Message-ID: <870210151039.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 10 Feb 87 10:38 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
I read the current document last night and was appalled at the
complexity of the rules that were used to explain the inheritance of the
characterisics of slot-descriptions.
Is this before or after Dick's venture at improving the way it's
described? The hardcopy I have (from Jan 31) doesn't look extremely
complicated, certainly less complicated than earlier attempts. The
English does need to be cleaned up a bit to make it crystal clear,
though.
I think it's fundamentally complicated, because :initform, :allocation,
and :type have been specified by the group to work three different ways,
and changing any one of them to work the same as another breaks
something. My opinion is that the only way to simplify it would be
to get rid of some features.
I also realized that accessors
and readers MUST be inherited. A new method need not be built for every
class if the implementation guarantees that the method inherited still
works. But whenever there is a change of the :allocation
characteristic, every accessor and reader in the inheritance chain must
have a new method created for it.
I don't believe this is true. Could you specify some reasons why new
methods would have to be created? And do those reasons mean that the
following will not work?
(defclass c1 () (s))
(defclass c2 (c1) ((s :allocation :class :initform 1)))
(defmethod foo ((self c1)) (with-slots (self) (print s)))
(foo (make-instance 'c2))
How does this relate to the remark in the inheritance section
"Methods that access slots know only the name of the slot and
the type constraint ..."?
∂10-Feb-87 1330 Bobrow.pa@Xerox.COM Re: Inheritance of Slots
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Feb 87 13:30:37 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 10 FEB 87 13:28:59 PST
Date: 10 Feb 87 13:27 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Inheritance of Slots
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 10 Feb 87 15:10 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870210-132859-7240@Xerox>
I read the current document last night and was appalled
at the complexity of the rules that were used to explain the
inheritance of the characterisics of slot-descriptions.
Is this before or after Dick's venture at improving the way
it's described? The hardcopy I have (from Jan 31) doesn't look
extremely complicated, certainly less complicated than earlier
attempts. The English does need to be cleaned up a bit to make it
crystal clear, though.
Yes it is different in style completely. It makes a mathematical
statement of the inheritance rules. It is three times longer. I don't
think it changes the intent.
I think it's fundamentally complicated, because :initform,
:allocation, and :type have been specified by the group to work
three different ways, and changing any one of them to work the same
as another breaks something. My opinion is that the only way to
simplify it would be to get rid of some features.
I would be happy to get rid of :type at this point, and allow :type to
be added by the metaobject protocol using
compute-effective-slot-description.
I wouldn't mind it if one always had to (re)specify an initform if one
changed the allocation, and if allocation always defaulted to :instance
in any specification. This would mean that you couldn't add an accessor
to :dynamic or :class slots without repeating the :allocation. For
:class slots that would of course mean a slot in this class, as opposed
to having another way to access the one up above. To do the latter, one
could simply use defmethod.
I also realized that accessors and readers MUST be
inherited. A new method need not be built for every class if
the implementation guarantees that the method inherited still
works. But whenever there is a change of the :allocation
characteristic, every accessor and reader in the inheritance
chain must have a new method created for it.
I don't believe this is true. Could you specify some reasons
why new methods would have to be created? And do those reasons
mean that the following will not work?
(defclass c1 () (s))
(defclass c2 (c1) ((s :allocation :class :initform 1)))
(defmethod foo ((self c1)) (with-slots (self) (print s)))
(foo (make-instance 'c2))
How does this relate to the remark in the inheritance section
"Methods that access slots know only the name of the slot and the
type constraint ..."?
I am assuming (perhaps wrongly) that the methods to access a slot would
optimize the slot access and that access to an instance slot would be
optimized very differently than access to a class slot or dynamic slot.
If this is true, then all methods that have optimized slot access will
have to be redefined. If the underlying implementation can both
optimize and handle all three types of access, then I am wrong.
∂10-Feb-87 1330 Bobrow.pa@Xerox.COM Meta-object protocol
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Feb 87 13:30:29 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 10 FEB 87 13:03:13 PST
Date: 10 Feb 87 13:02 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Meta-object protocol
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870210-130313-7181@Xerox>
In a meeting with RPG yesterday, it was agreed that the metaobject
protocol chapter would go out in the same package as the first two
chapters, but with a separate document number, and the following
disclaimer:
This document is a preliminary draft of the protocol. It was not
discussed extensively before being distributed, nor was it rationalized
with Chapters 1 and 2. It is being provided as a basis for the
presentation to be made at the X3J13 meeting in March 1987 so that
members of the committee can have a feeling for the entire proposed
object system. Most of the description is applicable to PCL, the model
portable implementation, and as such has been used by some people in the
community. The presentation in March will take into account changes
suggested by the Common Lisp Objects subcommittee between this
distribution and that meeting.
I am happy to put either of the following on the front:
1) Minimal responsibility
This document was written by Daniel G. Bobrow and Gregor Kiczales.
Contributers include everybody else
2) Maximal credit
This documetn was written by Daniel G. Bobrow, Linda G. DeMichiel,
Richard P. Gabriel, Sonya E. Keene, Gregor Kiczales, and David A. Moon
Contributers include the rest.
Or any compromise in between. Since you have only had a brief chance to
look at the document, please let me know which credit line you prefer.
Since by the time March comes, I hope we will have had a chance to work
on this document, and make 2 true, feel free to choose that alternative.
Please respond to this message so I know your feelings.
danny
∂10-Feb-87 1438 RPG Inheritance of Slots
To: common-lisp-object-system@SAIL.STANFORD.EDU
My ``venture'' at re-describing was an attempt to do exactly one
thing: To present the rules completely and unambiguously. LGD and
I had a very hard time understanding them as presented by Moon,
mostly because of English problems, and also because we couldn't
believe that the simple prose explained something as complex as
it does.
Once we are all in agreement that these rules do what we want, the
tremendous effort it will take to discover the best writeup can
begin.
As you can all see, the exercise in precision has alerted Danny to
aspects of the rules that he apparently didn't realize during the
earlier discussions. On the topic of accessor and readers, Moon's
writeup left no ambiguity, however.
-rpg-
∂10-Feb-87 2229 RPG Documents
To: common-lisp-object-system@SAIL.STANFORD.EDU
The documents are just about ready to go onto [cls,lsp]. They will be
mailed out friday afternoon, I believe. I will be out of town until next
Wednesday. Until I return, the protection on [cls,lsp] will prevent any
accidental overwriting of the files. This way people who wish to FTP them
for early perusal will know they are getting the very thing that is being
mailed.
Once they have been digested by people we will decide what to do.
I think it's reasonable to let the documents sit for a while for
people to gather their thoughts about what's left.
First, Danny and Gregor will be sending out a preliminary version of a
draft for chapter 3. It will have a separate document number so that
people will be able to refer to the reasonably well-thought-out chapter
1-2 draft without including the hot-out-of-the-oven chapter 3. We should
think about what to do with chapter 3.
Second, MAKE-INSTANCE was left unspecified, and the things it supercedes
(MAKE-METHOD etc) were left in chapters 1 and 2.
Third, Danny mentioned some discomfort with respect to inheritance of slot
descriptions as described in chapter 1. Again, I tried to make it precise
and unambiguous so that we can all see what it is we are buying into.
Fourth, I think we should seriously think about the overall complexity of
the specification and what it specifies. I think the complexity is a little
high for something on which to standardize. The descriptions of the aspects
of it are very complex in places, mostly because there is no vocabulary
or a priori mental model of the concepts.
LGD will be around while I'm away, but she (and I) are pretty burned out
after a solid week of 8 - 10 hours a day on this document (!).
Enjoy.
-rpg-
∂11-Feb-87 0857 kempf%hplabsc@hplabs.HP.COM Re: Meta-object protocol
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 11 Feb 87 08:56:53 PST
Received: from hplabsc by hplabs.HP.COM ; Wed, 11 Feb 87 07:56:11 pst
Received: by hplabsc ; Wed, 11 Feb 87 07:55:49 pst
Date: Wed, 11 Feb 87 07:55:49 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8702111555.AA13823@hplabsc>
To: Bobrow.pa@Xerox.COM, common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Meta-object protocol
I have read through the meta-object protocol posting and have
some comments, but would prefer to wait until the concepts and
functions chapters (which I believe were called Chapters 1 & 2
in Danny's note?) are ready for distribution, so I can cross
check. Some of my comments are the result of 6 months of working
with the PCL meta-object protocol and trying to port the result
to Kyoto Common Lisp, in the event the committee is interested
in experiences with the existing PCL meta-object implementation.
Jim Kempf kempf@hplabs.hp.com
∂12-Feb-87 1816 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: ensure-generic-function
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 12 Feb 87 18:15:58 PST
Received: from relay2.cs.net by RELAY.CS.NET id af14773; 12 Feb 87 19:33 EST
Received: from ti-csl by csnet-relay.csnet id dg20055; 12 Feb 87 19:30 EST
Received: from dsg (juliett.ARPA) by tilde id AA00230; Thu, 12 Feb 87 12:13:49 cst
Received: FROM Jenner BY dsg Via CHAOS-NET with CHAOS-MAIL; 12-Feb-87 07:22:36
Message-Id: <2749123430-91366@Jenner>
Sender: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
Date: 12-Feb-87 07:23:50
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Gregor.pa@XEROX.COM
Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: ensure-generic-function
In-Reply-To: In-Reply-To: Msg of 6-Feb-87 14:14:00 from Gregor.pa@xerox.comMsg of 6-Feb-87 14
Date: 6-Feb-87 14:14:00
From: Gregor.pa@xerox.com
Try this for ensure-generic-function:
ensure-generic-function <symbol>
&key (<generic-function-class>
(class-named 'standard-generic-function))
(make-exisiting-function-default-p nil)
If symbol is fboundp to a generic-function of the same class as
<generic-function-class> then this function does nothing
and returns the generic function object.
If symbol is fboundp to a generic-function of some other class, the
generic-function class changing protocol is followed, see chapter3.
If we don't want the type of the generic function to be changed, we can
pass (CLASS-NAMED 'GENERIC-FUNCTION) to the keyword-arg
:GENERIC-FUNCTION-CLASS.
If symbol not foundp a generic function of generic-function-class is
created and put in symbol's function cell.
If this function is meant to be used to normalize the argument to
GET-METHOD then it's not okay to create the generic function. We can
work around it by checking if the symbol is FBOUNDP before calling it
but a situation like this seems to be frequent enough so
ensure-generic-function should handle it.
If symbol is boundp to a function, and make-exisiting-function-default-p
is not nil, a generic-function is created, put in the function cell, a
default method is added to the generic-function and the symbol's
previous function cell value is used as the function for the default
method.
If symbol is fboundp to a function and make-exisiting-function-default-p
is nil an error is signalled.
If symbol names a macro or a special form, an error is signalled.
OK.
∂12-Feb-87 1838 LGD Documents
To: common-lisp-object-system@SAIL.STANFORD.EDU
The draft of the spec that is being sent out to the X3J13 committee is
now available on Sail. New files on [CLS,LSP] are concep.tex, concep.dvi,
functi.tex, functi.dvi. (Symfun.dvi and symcon.dvi have stripped-down
fonts to accommodate the Symbolics printers.) Macros.tex has also been
updated--anyone who prefers to TEX files locally will need to ftp the
new copy of that also.
lgd
∂18-Feb-87 1437 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: ensure-generic-function
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 18 Feb 87 14:36:42 PST
Received: from relay2.cs.net by RELAY.CS.NET id aa07115; 18 Feb 87 17:03 EST
Received: from ti-csl by csnet-relay.csnet id ad02241; 18 Feb 87 17:02 EST
Received: from dsg (juliett.ARPA) by tilde id AA02284; Wed, 18 Feb 87 15:36:06 cst
Received: From Jenner By dsg Via CHAOS-NET With CHAOS-MAIL; Wed, 18 Feb 87 15:37:33 CST
Message-Id: <2749671395-289490@Jenner.ti-7>
Date: Wed, 18 Feb 87 15:36:35 CST
Sender: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Gregor.pa@XEROX.COM
Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: ensure-generic-function
In-Reply-To: Msg of 6-Feb-87 14:14:00 from Gregor.pa@xerox.com
Date: 6-Feb-87 14:14:00
From: Gregor.pa@xerox.com
Try this for ensure-generic-function:
ensure-generic-function <symbol>
&key (<generic-function-class>
(class-named 'standard-generic-function))
(make-exisiting-function-default-p nil)
If symbol is fboundp to a generic-function of the same class as
<generic-function-class> then this function does nothing
and returns the generic function object.
If symbol is fboundp to a generic-function of some other class, the
generic-function class changing protocol is followed, see chapter3.
If we don't want the type of the generic function to be changed, we can
pass (CLASS-NAMED 'GENERIC-FUNCTION) to the keyword-arg
:GENERIC-FUNCTION-CLASS.
If symbol not foundp a generic function of generic-function-class is
created and put in symbol's function cell.
If this function is meant to be used to normalize the argument to
GET-METHOD then it's not okay to create the generic function. We can
work around it by checking if the symbol is FBOUNDP before calling it
but a situation like this seems to be frequent enough so
ensure-generic-function should handle it.
If symbol is boundp to a function, and make-exisiting-function-default-p
is not nil, a generic-function is created, put in the function cell, a
default method is added to the generic-function and the symbol's
previous function cell value is used as the function for the default
method.
If symbol is fboundp to a function and make-exisiting-function-default-p
is nil an error is signalled.
If symbol names a macro or a special form, an error is signalled.
OK.
Patrick.
∂18-Feb-87 1438 Moon@STONY-BROOK.SCRC.Symbolics.COM Things we should do to prepare for the March meeting
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Feb 87 14:38:19 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 73453; Wed 18-Feb-87 17:37:17 EST
Date: Wed, 18 Feb 87 17:37 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Things we should do to prepare for the March meeting
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870218173711.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
There are quite a few errors in the document. I believe it is important
to distribute an errata sheet at the meeting. I have read the document
very carefully and am producing a first draft of an errata sheet, which
I will send out in a separate mail message, either today or tomorrow. I
assume we can produce a final draft errata sheet, acceptable to
everyone, through the mail.
The glossary section should be finished, checked for consistency with
the rest of the document, and distributed at the meeting. This will
make the document easier to understand.
Make-instance should be resolved. There are several other issues
(perhaps I will put together a list in a day or two) that should be
resolved also if we have additional time.
I have not yet read the meta-object chapter carefully enough to comment
on it. Maybe next week.
∂18-Feb-87 1502 Gregor.pa@Xerox.COM Re: ensure-generic-function
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Feb 87 15:02:32 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 18 FEB 87 14:48:48 PST
Date: 18 Feb 87 14:48 PST
From: Gregor.pa@Xerox.COM
Subject: Re: ensure-generic-function
In-reply-to: Patrick H Dussud
<DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>'s message of Wed, 18 Feb 87
15:36:35 CSTTo: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
cc: Gregor.pa@Xerox.COM, Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870218-144848-2907@Xerox>
If we don't want the type of the generic function to be changed, we
can
pass (CLASS-NAMED 'GENERIC-FUNCTION) to the keyword-arg
:GENERIC-FUNCTION-CLASS.
I am not sure I understand what this means.
If this function is meant to be used to normalize the argument to
GET-METHOD then it's not okay to create the generic function. We
can
work around it by checking if the symbol is FBOUNDP before calling
it
but a situation like this seems to be frequent enough so
ensure-generic-function should handle it.
It seems to me that this error case is better dealt with outside of
ensure-generic-function. I guess that means I don't see this function
being used to normalize the first argument to get-method very often. I
expect it to be used to normalize the first argument to add-method more
often.
Basically, there are so many different ways I can imagine wanting to be
careful about what to do with the value that is already in the function
cell, that I think the best thing to do is make this function have a
simple behavior and let people put checking code around calls to it when
that is appropriate.
∂18-Feb-87 2139 Moon@STONY-BROOK.SCRC.Symbolics.COM Errata for 87-002
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Feb 87 21:39:19 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 73697; Thu 19-Feb-87 00:38:18 EST
Date: Thu, 19 Feb 87 00:38 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Errata for 87-002
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870219003802.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Here is my first draft of the errata sheet for the 87-002 documents.
This doesn't get into things that need to be explained better in a major
way, nor into things that are controversial, only things where what the
document says is obviously in error. I'll send out the other things
separately. Comments, corrections, and additions are of course highly
welcome. I tried to find everything but no doubt overlooked some errors.
1-4 seventh paragraph: The distinguished class T is mentioned but I don't
think its characteristics are ever described in the document, except by
implication. Add the sentence:
T has no superclasses and is a superclass of every class except itself.
1-6 last paragraph: At the end of the second sentence: change "lexically
available" to "lexically available as if they were variables".
1-10: Replace the last sentence with "There is also a method
for {\bf setf} of {\tt C2-S3} that writes the value of {\tt S3}."
1-11 second paragraph: The vague word "access" is used without definition.
Add the sentence: "In this context, an instance is said to be
accessed when a generic function is called with the instance as an
argument that is used for method selection, or when {\bf slot-value}
is called with the instance as its first argument."
1-11 third paragraph: Remove the sentence "The function {\bf change-class}
is called when the number of instance variables changes or when the name of
any instance variable changes" since there is no such concept as "instance
variable" in this standard. Replace it with the sentence:
"When a class is redefined in such a way that the set of local slots
accessible to an instance of the class is changed, or the order of slots
in storage is changed, updating an instance of the class calls the function
{\bf change-class}."
1-11 fourth paragraph: Delete the entire paragraph, it isn't true. Replace
it with this paragraph:
Because the class C-sub-O does not have a name, writing a method for
class-changed that is specialized to a particular C-sub-O
must be done through the functional interface, using add-method rather
than defmethod.
1-11 fifth paragraph third sentence: Change "Each slot of the new version"
to "Each local slot of the new version". Last sentence: Delete "For
local slots," since we are only talking about local slots anyway.
1-11 last paragraph: Change "the value of that slot will be the same
in both instances" to "the value of that slot is unchanged". Since only
one instance is involved, we can't say "both instances."
1-11 last paragraph: Break the paragraph after the third sentence so local
slots and shared slots are discussed in separate paragraphs. Clarify that
the paragraph discussing shared slots refers to what happens at the time
the class is redefined, and shared slots are not affected by updating an
instance nor by the values of local slots.
1-12 last paragraph: Change "Whether {\bf defclass} is allowed to change
the metaclass" to "Whether {\bf defclass} is allowed to change the
metaclass, and whether redefining a class updates existing instances,".
1-18 first paragraph under "Introduction to setf Generic Functions":
Change "(setf (generic-function-name arguments) new-value)"
to "(setf (function-name arguments) new-value)" because the base
function does not have to be generic, in fact it does not even have to
be defined.
1-18 last paragraph: The term "parameter specifier" is used in a way that
is inconsistent with its use by CLtL and there are a couple of typographical
problems. Replace the entire paragraph with:
Each method has a {\bit specialized lambda-list}, which determines
when that method can be selected. A specialized lambda-list is like
an ordinary lambda-list except that a {\bit specialized parameter} may occur
instead of the name of a parameter. A specialized parameter is a list,
{\tt ({\it variable-name parameter-specializer-name\/})}. Every
parameter specializer name is a Common Lisp type specifier, but the only
Common Lisp type specifiers that are valid as parameter specializer names
are the following:
1-19: Delete the first line "In short..." since the two bulleted items are
now introduced by the preceding paragraph.
1-19 fourth paragraph, beginning "Only required parameters can be specialized":
The term "parameter specifier" is misused again. Replace the paragraph with:
Only required parameters can be specialized, and each required parameter
must have an associated parameter specializer. For notational simplicity,
ordinary lambda-list syntax can be used, that is, a parameter name can be
used instead of a specialized parameter. In this case the parameter
specializer defaults to the class named {\bf t}, the class of all objects.
1-19 fifth paragraph: Change "when the class of each required argument"
to "when each required argument".
1-19, seventh, eighth, and tenth paragraphs, discussing the relationship of
parameter specializers to type specifiers: Change "parameter specializer"
to "parameter specializer name" throughout these paragraphs, to be
consistent with the terminology used in earlier paragraphs.
1-19 tenth paragraph: Change "always part of the generic function"
to "always applicable".
1-19 last paragraph fourth sentence: Change "cons" to "list".
1-22 second paragraph: Change "the specializers must be quoted objects
(otherwise" to "the specializers must be equal (otherwise".
1-23 first line: Change "defmacro" to "defmethod".
1-25 sixth paragraph: Change "All {\bf :around} methods run before any
primary methods run." to "All {\bf :around} methods run before any
non-{\bf :around} methods run."
2-5 Values paragraph: Replace the whole sentence with
"The value is {\it generic-function}." to clarify that the value
is EQ to the argument.
2-8 Purpose paragraph: Add the sentences "The generic function
{\bf change-class} is invoked automatically by the system after
{\bf defclass} has been used to redefine an existing class.
It can also be explicitly invoked by the user."
2-8 Values paragraph: Replace the whole sentence with
"The value is {\it instance}." to clarify that the value
is EQ to the argument.
2-11 Purpose paragraph: Delete the sentences "The generic function
{\bf change-class} is invoked automatically by the system after
{\bf defclass} has been used to redefine an existing class.
It can also be explicitly invoked by the user." Add the sentence
"The function {\bf class-changed} is called only by
the function {\bf change-class}."
2-11 second Arguments paragraph: Delete the second sentence. It lost
its intended meaning as a result of previous editing.
2-11 first Remarks paragraph: Delete this. It contradicts an
example on page 2-8 and it isn't true.
2-11 second Remarks paragraph: Some occurrences of change-class should be
class-changed and there are a couple of terminological problems ("copy",
"part"). Replace the paragraph with:
The arguments to {\bf class-changed} are computed by {\bf change-class}.
The first argument is an instance of the original class
created to hold the old slot values temporarily.
This argument has dynamic extent within {\bf class-changed},
and therefore it is an error to reference it in any way
once {\bf class-changed} returns.
2-15 last line: Delete this. Defclass has no effect on the value cells
of symbols.
2-17 second paragraph: Delete ", from their superclasses, and so on".
2-17 :allocation bullet: Change "in the class instance" to "in each
instance".
2-18 first bullet (:type). There is no discussion of the meaning and
enforcement of :type. Add the following (stolen from CLtL p.310):
This specifies that the contents of the slot will always be of the
specified data type. This is entirely analogous to the declaration of a
variable or function; indeed, it effectively declares the result type of
the reader generic function when applied to an object of this class. An
implementation may or may not choose to check the type of the new object
when initializing or assigning to a slot.
2-18 :accessor-prefix, :reader-prefix bullets: Change "These ... functions
are interned" to "These ... function names are interned".
2-26 short-form-option syntax: Delete the :order clause.
2-27 fourth bullet: Delete it.
2-29 first paragraph: Replace the next to last sentence with: "If {\bf
:description} is not specified, a default description is generated based on
the variable name and the qualifier patterns, and on whether this
method-group includes the unqualified methods."
2-33 third paragraph: Change "If no generic function is currently named by
the symbol {\it name\/}" to "If {\tt (fboundp {\it name\/})} is {\bf nil}"
to match the terminology used on page 2-21.
2-34 first paragraph: Change "primary (in this case, unqualified) methods"
to "unqualified methods".
2-34 second paragraph: Same problem with "parameter specifier" as on 1-18.
Replace the first two sentences of the paragraph with:
The {\it specialized-lambda-list\/} argument is like an ordinary function
lambda-list except that required parameter names can be replaced by
specialized parameters. A specialized parameter is a list of the form
{\tt ({\it variable-name parameter-specializer-name\/})}.
[This paragraph duplicates information found elsewhere so perhaps it
should be shortened.]
2-35 syntax for specialized-setf-lambda-list: Change "specializer" to
"parameter-specializer-name".
2-38 fourth Arguments paragraph: Change "If the first argument is a symbol"
to "If the first argument is a symbol that names a class".
2-38 last Arguments paragraph: Change "If the first argument is a symbol"
to "If the first argument is a symbol that has a setf generic function
associated with it".
2-39 last Arguments paragraph: Change "second" to "errorp".
2-41 second Purpose paragraph: Delete "to the top level".
2-46 second Purpose paragraph first sentence: It was not intended to
guarantee that the returned value is a list with certain objects in its car
and cdr. Add the phrase "or a form with equivalent effect" at the end of
the sentence.
2-47 Values paragraph: same as the preceding.
2-48 second Purpose paragraph: Delete "to the top level".
2-53 last Arguments paragraph: Change "second" to "errorp".
Change (twice) "If there is no such method" to
"If {\it generic-function} does not know {\it method}".
2-53 Values paragraph: Replace the whole sentence with
"The value is {\it generic-function}." to clarify that the value
is EQ to the argument.
2-55 last paragraph first sentence: Delete "or a superclass".
2-55 last paragraph fourth sentence: Change "not a subclass of the
specified class" to "not the specified class or a subclass of the
specified class".
2-55 last paragraph fifth sentence: Change "superclass of the instance" to
"superclass of the actual class of the instance" and change "different"
to "smaller".
2-56 second paragraph: Change "using the accessor function" to "calling the
accessor function", "is used to access" to "is called to access", and
"accesses the slots by using" to "accesses the slots by calling".
2-56 Values paragraph: Change "value" to "values" to clarify that the
body can return multiple values.
∂19-Feb-87 1323 RPG CLOS Response
To: common-lisp-object-system@SAIL.STANFORD.EDU
Monday I presented CLOS to the SmallTalk and Scheme folks at Tektronix in
Beaverton, Oregon. The response was disappointing, though one would expect
SmallTalk people to respond negatively. However, they made some good
points.
First, they were skeptical about the class precedence list and the wary of
the importance of it. Their concern was that much of the behavior of the
system depended on it while the user couldn't control it easily nor could
a user understand it well.
There was little problem with the topological sorting, and the problems
were with what happened when the explicit rules (a class precedes its
superclasses and the local precedence order is preserved) underconstrained
the ordering. They did not understand the ``tiebreaker.'' The Scheme
people had an interesting proposal: the specification should say that the
CPL is a topological sort of the C and its superclasses subject to the
explicit rules, but that the user could not depend on what happened when
the problem was underconstrained. They proposed that the CPL computation
should explicitly pick a random but valid total ordering when
nondeterminism happens.
This radical suggestion can be made palletable by adding the following
things.
1. There should be a flag that controls when the system warns about
nondeterminism;
2. There should be a new class option which is of this form:
(:relations (C1 C2) ... (Cn-1 Cn)) in DEFCLASS which give
further constraints to the ordering of superclasses.
This way the user can specify the ordering without having to write his own
CPL computation function. We could also have some means of using a default
tiebreaker, which would probably be the one we have now. I imagine people would
program by writing defclasses, watching or thinking about what's happening, and
then adding the further constraints to get the desired behavior. The reasonable
behavior of the programming environment tools is important here.
Second, they thought that the complexity of slot description combination
was complex. I agree.
Third, they thought that method combination was complex. Because we all
seem to agree that method combination is important, this probably
indicates a different presentation methodology or a different organization
to the system is desirable. One suggestion is to present CLOS so that it
looks as much like CommonLoops as possible at first glance and to then
bring in method combination. That is, maybe a good idea is to break up
the current first chapter into two chapters where the first chapter
defines only unqualified methods along with the behavior of methods under
CALL-NEXT-METHOD. The second chapter could show what happens when methods
are qualified using standard method combination.
At least a conceptual simplicity in presentation must be maintained. LGD
and I only cleaned up the description of method combination enough that it
was not grossly inconsistent, and I think it needs a major amount of
thought to present it well.
-rpg-
∂19-Feb-87 1422 RPG Comments On Moon's Errata (Chapter 1 only)
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Moon writes:
``1-11 fourth paragraph: Delete the entire paragraph, it isn't true. Replace
it with this paragraph:
Because the class C-sub-O does not have a name, writing a method for
class-changed that is specialized to a particular C-sub-O
must be done through the functional interface, using add-method rather
than defmethod.''
I think the original statement is true, and it is because of that fact
that Moon's re-statement would be true. Possibly both statements should
be made, suitably phrased:
Because redefining a class does not change its name, the class $C\sub o$
does not have a name. Thus, writing a method for {\bf class-changed} that
is specialized to a particular $C\sub o$ must be done through the
functional interface, using {\bf add-method} rather than using {\bf
defmethod}. See the section ``Introduction to Methods.''
I think this might make the situation clearer to the reader.
Moon writes:
``1-18 first paragraph under "Introduction to setf Generic Functions":
Change "(setf (generic-function-name arguments) new-value)"
to "(setf (function-name arguments) new-value)" because the base
function does not have to be generic, in fact it does not even have to
be defined.''
If this is correct, then it should be: ``(setf (symbol arguments)
new-value)''
Moon writes:
``1-18 last paragraph: The term "parameter specifier" is used in a way that
is inconsistent with its use by CLtL and there are a couple of typographical
problems. Replace the entire paragraph with:
Each method has a {\bit specialized lambda-list}, which determines
when that method can be selected. A specialized lambda-list is like
an ordinary lambda-list except that a {\bit specialized parameter} may occur
instead of the name of a parameter. A specialized parameter is a list,
{\tt ({\it variable-name parameter-specializer-name\/})}. Every
parameter specializer name is a Common Lisp type specifier, but the only
Common Lisp type specifiers that are valid as parameter specializer names
are the following:''
The comment about bad use of ``parameter specifier'' is correct; I only
wish he had brought it up sooner. I think the re-wording is not as good as
the original, though. We need to connect the linguistic item {\it
parameter-specializer-name} (typeset in italics) with an English phrase that
can be explained. The original had more information about the relationship
between parameter specializer names and Common Lisp type specifiers, and the
implicitness of that information in Moon's re-wording (and in earlier versions)
rendered the whole section incomprehensible.
Here is a possible re-wording:
Each method has a {\bit specialized lambda-list}, which determines when
that method can be selected. A specialized lambda-list is like an
ordinary lambda-list except that a {\bit specialized parameter} may occur
instead of the name of a parameter. A specialized parameter is a list,
{\tt ({\it variable-name parameter-specializer-name\/})}, where {\it
parameter-specializer-name\/} is a parameter specializer name. Every
parameter specializer name is a Common Lisp type specifier, but the only
Common Lisp type specifiers that are parameter specializers names are type
specifier symbols with corresponding classes and type specifier lists of
the form {\tt ({\bf quote} {\it object})}. The form {\tt ({\bf quote} {\it
object})} is equivalent to the type specifier {\tt ({\bf member} {\it
object\/})}.
Moon writes:
``1-19 fourth paragraph, beginning "Only required parameters can be specialized":
The term "parameter specifier" is misused again. Replace the paragraph with:
Only required parameters can be specialized, and each required parameter
must have an associated parameter specializer. For notational simplicity,
ordinary lambda-list syntax can be used, that is, a parameter name can be
used instead of a specialized parameter. In this case the parameter
specializer defaults to the class named {\bf t}, the class of all objects.''
Again, the substantive point is well-taken, but the re-wording is bad.
The style has become flabby and imprecise. If you need to say ``that is,''
then you said the wrong thing in the first place. The paragraph is talking
about the required parameters, and the comment linking the syntax of them to
lambda-list syntax doesn't restrict the lambda-list syntax of interest to
the lambda-list syntax of required parameters. It is usually good to link
new concepts with old ones, but this wording simply confuses the issue.
Try this instead:
Only required parameters can be specialized, and each required parameter
must be a specialized parameter. For notational simplicity, if some
required parameter in a specialized lambda-list is simply a variable
name, the corresponding parameter specifier is taken to be {\tt
({\it variable-name} {\bf t})}.
Moon writes:
``1-19, seventh, eighth, and tenth paragraphs, discussing the relationship of
parameter specializers to type specifiers: Change "parameter specializer"
to "parameter specializer name" throughout these paragraphs, to be
consistent with the terminology used in earlier paragraphs.''
Nope. Moon missed the point, which, I guess, needs to be clarified even
more. The second paragraph on page 19 defines parameter specializers (PS)
in terms of parameter specializer names (PSN). The PSN's correspond to
names of classes while the PS's are the classes. ``Satisfaction'' operates
on the classes. This is so that the functional interface (ADD-METHOD et
al) can take PS's and DEFMETHOD can take PSN's. Otherwise we cannot
explain the change-class protocol.
I'll think about the Chapter 2 comments later.
-rpg-
∂19-Feb-87 1524 DLW@ALDERAAN.SCRC.Symbolics.COM CLOS Response
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 19 Feb 87 15:24:47 PST
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 52619; Thu 19-Feb-87 18:23:49 EST
Date: Thu, 19 Feb 87 18:23 EST
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: CLOS Response
To: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 19 Feb 87 16:23 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870219182341.9.DLW@CHICOPEE.SCRC.Symbolics.COM>
Date: 19 Feb 87 1323 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Third, they thought that method combination was complex. Because we all
seem to agree that method combination is important, this probably
indicates a different presentation methodology or a different organization
to the system is desirable. One suggestion is to present CLOS so that it
looks as much like CommonLoops as possible at first glance and to then
bring in method combination. That is, maybe a good idea is to break up
the current first chapter into two chapters where the first chapter
defines only unqualified methods along with the behavior of methods under
CALL-NEXT-METHOD. The second chapter could show what happens when methods
are qualified using standard method combination.
This suggestion doesn't seem very consistent with your earlier (months
ago) statements about the philosophy of this document. Earlier, you
pointed out that we are writing a specification, mainly intended for
implementors and language experts, with the goal of making sure that
each implementation of CLOS will be compatible with each other, to
assure portability. You even criticised some of the early draft text
because it was too pedagogical. I think you convinced all of us that
you were right, that our priorities should be on specificity and
exactness, rather than on providing a friendly, teaching approach, for
purposes of this document. I'm sure we all agree that at least one
friendly, pedagogical explanation of CLOS can and will appear in the
future (probably many), after CLOS is defined and accepted, but the
present document isn't it.
∂19-Feb-87 1743 Moon@STONY-BROOK.SCRC.Symbolics.COM CLOS Response
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 19 Feb 87 17:43:36 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 74578; Thu 19-Feb-87 20:18:19 EST
Date: Thu, 19 Feb 87 19:58 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: CLOS Response
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 19 Feb 87 16:23 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870219195839.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 19 Feb 87 1323 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Monday I presented CLOS to the SmallTalk and Scheme folks at Tektronix in
Beaverton, Oregon. The response was disappointing, though one would expect
SmallTalk people to respond negatively. However, they made some good
points.
I think this feedback is valuable, but should be put into perspective.
Comments below.
First, they were skeptical about the class precedence list and the wary of
the importance of it....They proposed that the CPL computation
should explicitly pick a random but valid total ordering when
nondeterminism happens.
I sent mail in November with some strong arguments for why this won't work.
I think it was November; I can dig up the exact message reference if you like.
This radical suggestion can be made palletable by adding the following
things.
1. There should be a flag that controls when the system warns about
nondeterminism;
We could do this if we didn't mind adding extra complexity to the standard.
It would have to be a class option, not a global flag, so that classes using
both styles could coexist in the same Lisp.
2. There should be a new class option which is of this form:
(:relations (C1 C2) ... (Cn-1 Cn)) in DEFCLASS which give
further constraints to the ordering of superclasses.
Flavors has this but there didn't seem to be much interest in putting it into
the standard. Should we reconsider that decision, or would that be making
the standard too complex?
Second, they thought that the complexity of slot description combination
was complex. I agree.
The description in the document is horrendously overcomplicated. The
previous attempt was much simpler but still too hard to understand and
imprecise. For some reason we've had great difficulty explaining this
concept, even though it is actually rather simple. I've been planning on
mailing out a proposed better way of explaining slot inheritance for
discussion, but haven't had time to finish it yet. In any case something
clearly has to be done.
Third, they thought that method combination was complex. Because we all
seem to agree that method combination is important, this probably
indicates a different presentation methodology or a different organization
to the system is desirable. One suggestion is to present CLOS so that it
looks as much like CommonLoops as possible at first glance and to then
bring in method combination. That is, maybe a good idea is to break up
the current first chapter into two chapters where the first chapter
defines only unqualified methods along with the behavior of methods under
CALL-NEXT-METHOD. The second chapter could show what happens when methods
are qualified using standard method combination.
This is the reaction one would expect from people used to Smalltalk's
send-to-super mechanism. I think you would find the analogous reaction, that
the call-next-method feature is complex and should be relegated to the back
of the book, if you presented it to people who were used to method combination.
I think the order of presentation should be left the way it is and we should
concentrate on the remaining substantial issues that need to be resolved.
At least a conceptual simplicity in presentation must be maintained. LGD
and I only cleaned up the description of method combination enough that it
was not grossly inconsistent, and I think it needs a major amount of
thought to present it well.
I thought we were trying to be precise with this document, rather than trying
to be easy to understand.
∂19-Feb-87 1752 RPG Consistency
To: common-lisp-object-system@SAIL.STANFORD.EDU
At this point I'm worried about a couple of new things: first, that
the Common-Lisp-skeptics will accuse us of doing to object-oriented
programming what we did to Lisp: obfuscate and ruin it; second, that
the proposal might be in jeopardy because it is too complex.
The people at Tektronix had no trouble understanding what I said, nor
did they fail to understand CLOS. They were appalled at the complexity
and questioned whether that complexity was necessary.
I'm suggesting, also, that maybe the organization of the system
should be made to reflect the proposed organization of the document.
The point would be to make CLOS less intimidating to the new user.
I still believe that we are writing a specification, and it would be wrong
to put fluffy, imprecise language into the document. I think from my
comments about Moon's errata you can still see this attitude. And if you
compared the draft material as of 2 weeks ago with the current draft you
will see a major movement towards consistency and preciseness, even at the
expense of pretty language - it may not be perfect, but a lot of
what was there before was embarrassingly bad.
When I decide to write things using mathematical notation, for example, it
is because I cannot think of how to unambiguously express the concepts in
English. (Also, if the concepts were simpler, they could be expressed in
prose more easily.)
I must admit a little bit second-thinking about CLOS and how much
more time I can justify putting into it.
-rpg-
∂20-Feb-87 0928 DLW@ALDERAAN.SCRC.Symbolics.COM Consistency
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 20 Feb 87 09:28:39 PST
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 52917; Fri 20-Feb-87 12:27:39 EST
Date: Fri, 20 Feb 87 12:27 EST
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Consistency
To: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 19 Feb 87 20:52 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870220122725.1.DLW@CHICOPEE.SCRC.Symbolics.COM>
Date: 19 Feb 87 1752 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
At this point I'm worried about a couple of new things: first, that
the Common-Lisp-skeptics will accuse us of doing to object-oriented
programming what we did to Lisp: obfuscate and ruin it; second, that
the proposal might be in jeopardy because it is too complex.
I share your worries about this.
However, it's not too surprising, since all we're giving the community
is a reference manual. Reference manuals are good for DEFINING a
standard, but they aren't so good for SELLING a standard.
(For example, I am absolutely convinced that Scott Fahlman's snarling
antipathy to Flavors is due entirely to the fact that the Flavors
documentation that Moon and I wrote doesn't separate the easy,
everyday features from the sophisticated, only-for-experts features,
thus giving a false impression that you must master great complexity
in order to do even the simplest thing.)
Based on all my experience with technical writing, I don't think it's
practical or desirable to try to come up with a single document that
serves both as a precise reference for CLOS, and also as a friendly
introduction to CLOS.
I still believe that we are writing a specification, and it would be wrong
to put fluffy, imprecise language into the document...
When I decide to write things using mathematical notation, for example, it
is because I cannot think of how to unambiguously express the concepts in
English....
Exactly. The problem is that what you call "fluffy, imprecise
English" is often the best way to TEACH someone about something. You
use conversational English to establish the basic idea, the
motivation, the paradigm; then you use precise, rigorous, and maybe
even mathematical language to explain it in such a way that the user
can be sure of understanding all the cases, including complicated
interations, and so on. Papers like the ones mailed out as
X3J13/86-018, or something even gentler, are more like what you'd want
for teaching the basic concepts.
I don't know whether something like this could be produced in time for
distribution at the next X3J13 meeting. At least, though, when we
present the material, we can take that kind of gentle approach, and
remind people several times that what they're holding is a reference
manual, not a tutorial, and not to think that everybody would learn
CLOS by reading the reference manual.
∂20-Feb-87 2237 RPG CLOS
∂18-Feb-87 1210 DLW@ALDERAAN.SCRC.Symbolics.COM CLOS
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 18 Feb 87 12:09:44 PST
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 52043; Wed 18-Feb-87 14:52:26 EST
Date: Wed, 18 Feb 87 14:52 EST
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: CLOS
To: Moon@STONY-BROOK.SCRC.Symbolics.COM, RPG@SAIL.STANFORD.EDU
cc: bobrow.pa@XEROX.COM, gregor.pa@XEROX.COM,
SKeene@STONY-BROOK.SCRC.Symbolics.COM
In-Reply-To: <870218144058.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870218145202.5.DLW@CHICOPEE.SCRC.Symbolics.COM>
Line-fold: No
Pardon my cynicism, but it sounds as if the objections of the
Smalltalk people were exactly what you would expect if what they
really wanted to do was defend Smalltalk, or show why Smalltalk is
better than CLOS. "It's all too complicated, nobody needs that stuff,
and it'll be too slow." I'll certainly concede that it takes longer
to learn CLOS than to learn the equivalent stuff about Smalltalk, and
that some jobs are simple enough that you don't gain much from what
CLOS has that Smalltalk doesn't have. Part of the fundamental
motivation for CLOS is that we're designing it for an audience that
has tougher requirements than Smalltalk can fulfill.
∂20-Feb-87 2237 RPG CLOS
∂18-Feb-87 1142 Moon@STONY-BROOK.SCRC.Symbolics.COM CLOS
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Feb 87 11:42:28 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 73224; Wed 18-Feb-87 14:41:05 EST
Date: Wed, 18 Feb 87 14:40 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: CLOS
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
cc: bobrow.pa@XEROX.COM, gregor.pa@XEROX.COM,
SKeene@STONY-BROOK.SCRC.Symbolics.COM,
DLW@STONY-BROOK.SCRC.Symbolics.COM,
Moon@STONY-BROOK.SCRC.Symbolics.COM
In-Reply-To: The message of 18 Feb 87 13:19 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870218144058.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 18 Feb 87 1019 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
I was in Portland Monday, so I made a presentation of CLOS to
the local SmallTalk folks. Although I think I did a pretty good job
with the presentation (and so they said), I was not able to present
convincing, real-life examples of the various aspects of it.
The talk was somewhat impromptu, so I had nothing prepared, and my
examples were contrived in various ways. I think that for the X3J13
meeting it is important to give good examples. Especially
troublesome is method combination.
That's interesting. I'll keep this in mind as I start preparing my
presentation. However, it's always impossible to give really convincing
real-life examples of this stuff in a presentation format. The reason is
that, as a program organization paradigm, this stuff really only matters
in large programs. For any small program, the audience can always find
a "simpler" way to do it. It always ends up being "trust me, there really
are examples where this is useful, but it would take me a week to show
you one."
Their criticisms were:
1. method combination seems complicated.
I guess it's going to seem complicated to anyone from the Smalltalk world.
All we can do is try to explain it well.
2. the CPL is hokey, and maybe single inheritance is good enough.
They saw this as yet another reason to doubt multiple inheritance.
I am totally convinced that multiple inheritance is important, but I guess it's
going to seem complicated to anyone from the Smalltalk world.
3. the class-redefinition protocol is complex. They have a similar
problem (called the ``mutation problem')' in SmallTalk. They
provide *no* user-controllable protocol and have never received
a complaint from a user.
We have found it extremely useful and have received several user complaints
about the fact that the New Flavors redefinition protocol is not as complex as
the one proposed for the standard; in particular, the Flavors one doesn't allow
access to the old version of the instance.
4. They though generic function invocation would be too slow (even
without method combination).
This seems like a judgement of the smartness of the implementor. Surely cases that
only do what you can do in Smalltalk will be at least as fast as Smalltalk. If
multi-methods are slower, that doesn't have to slow down things that don't use them.
Question on scope of the X3J13 talk: Should it assume that the feature set
(multiple inheritance, method combination, generic functions, multi methods)
is a given and simply explain the proposed language for accessing the features?
Or should it try to sell people on our choice of particular features to include?
∂20-Feb-87 2242 RPG Meeting
To: common-lisp-object-system@SAIL.STANFORD.EDU
I can make a meeting on monday, but I'd like to be within hailing
distance of the main meeting in case a fight breaks out.
I don't especially mind an errata sheet as long as it doesn't
contain un-agreed-to proposed re-wordings. The factual errors
are ok to put there, but I'd rather not see listed as errata an
inferior re-wording of a clearly worded paragraph. I don't mind
re-wording things if the re-wording is better, but good wording
is the result of long, careful thought.
-rpg-
∂20-Feb-87 2255 RPG CPL
To: common-lisp-object-system@SAIL.STANFORD.EDU
You might wonder why I continue to harp on the CPL. Moon argues that
the CPL computation should do a clear, unambiguous thing. If it's intuitive,
all the better. Maybe so.
My worry is that most people, even after a lot of thought, will think of
it like this:
1. the CPL respects the superclass relationships
2. the CPL respects the order of direct superclasses
3. otherwise, it is a black box, and if the programmer doesn't like
it, he can supply his own.
The CPL is used all over the place, and it's not comforting to think that
the correctness of your program depends on a black box. Moon argued that
the New Flavors CPL algorithm did the right thing and was intuitive. He argued
that some huge number of users depended on it and liked it. So we tried
to figure out an alternative formulation that was easier to understand.
The result was that we found an example that showed that the algorithm
that did the right thing and that programmers loved did the wrong thing.
Moon thought this algorithm was the right thing for about a year (?).
Why is what we now have the right thing? Why aren't we trying to think
of a simple way for the user to have control of the CPL without making him
write his own algorithm? We can provide some default, but I think that
making someone write their own topological sort as the only alternative
is a loser.
Well, let's have the committee look over the proposal and make its
comments.
-rpg-
∂22-Feb-87 1054 RPG Away
To: common-lisp-object-system@SAIL.STANFORD.EDU
I'm away until Wednesday night. Please do not immolate each
other until I return.
-rpg-
∂23-Feb-87 1008 DLW@ALDERAAN.SCRC.Symbolics.COM CPL
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 23 Feb 87 10:07:41 PST
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 53681; Mon 23-Feb-87 13:06:32 EST
Date: Mon, 23 Feb 87 13:06 EST
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: CPL
To: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 21 Feb 87 01:55 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870223130627.8.DLW@CHICOPEE.SCRC.Symbolics.COM>
Date: 20 Feb 87 2255 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Moon thought this algorithm was the right thing for about a year (?).
Why is what we now have the right thing? Why aren't we trying to think
of a simple way for the user to have control of the CPL without making him
write his own algorithm? We can provide some default, but I think that
making someone write their own topological sort as the only alternative
is a loser.
The answer to this problem in New Flavors is a per-flavor option that
lets you explicitly add partial-order constraints. I think this would
be a good way to address the problems you raise. It means that for
relatively small or simple application, in which the first two rules
fully specify the order, the right thing happens automatically. For
larger or more complex applications, it let you explicitly control any
ambiguity that might be a problem, but does not force you to
completely enumerate every CPL (which would be a real pain in the
neck and make subsequent modifications awkward).
∂23-Feb-87 1041 Moon@STONY-BROOK.SCRC.Symbolics.COM Errata
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Feb 87 10:41:03 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 76668; Mon 23-Feb-87 13:41:22 EST
Date: Mon, 23 Feb 87 13:39 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Errata
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870223133957.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Here's one I missed:
1-6 first paragraph: Change ":instance" to ":instance or :dynamic".
∂23-Feb-87 1938 Moon@STONY-BROOK.SCRC.Symbolics.COM CPL
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Feb 87 19:37:55 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 77253; Mon 23-Feb-87 22:38:24 EST
Date: Mon, 23 Feb 87 22:36 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: CPL
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 21 Feb 87 01:55 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870223223657.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 20 Feb 87 2255 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
You might wonder why I continue to harp on the CPL....
Moon argued that
the New Flavors CPL algorithm did the right thing and was intuitive. He argued
that some huge number of users depended on it and liked it. So we tried
to figure out an alternative formulation that was easier to understand.
The result was that we found an example that showed that the algorithm
that did the right thing and that programmers loved did the wrong thing.
This is not quite accurate. The CPL algorithm in New Flavors and the one in
87-002 are very close in their effects. The example we found where they
differ is one in which the algorithm used in New Flavors fails to produce
the intuitive result. The programmers never loved the algorithm, nor even
knew in such detail what it did that they could distinguish between the New
Flavors algorithm and the 87-002 algorithm. What they liked was the result,
not the way it was computed.
What I argued against was other proposed algorithms that produced very
different results. What you argued against was algorithms whose description
was not very algorithmic. We both got what we wanted.
Why aren't we trying to think
of a simple way for the user to have control of the CPL without making him
write his own algorithm?
Does this mean that you want me to convert the following, extracted
directly from the Flavors documentation, to 87-002 terminology and
distribute it for comments, either in this working group or at the X3J13
meeting? If so, I'll be happy to do so.
@Topic[:component-order Option for defflavor]
Enables you to state explicitly the ordering constraints for
the flavor components whose order is important. You can use it to
relax ordering constraints on component flavors for which order is not
important. You can also use it to add ordering constraints on flavors
that are not components; this means that if this flavor is later mixed
with another flavor, the ordering of components takes into account the
constraints given by this option.
If :component-order is given, the order of flavor components at
the top of the defflavor form is no longer significant. The
arguments to :component-order are lists. The members of
each list are constrained to appear in the order they appear in
the list. Any component that does not appear in these lists has no
ordering constraints placed on it.
For example, the following form imposes many constraints on the ordering
of the seven flavor components:
(defflavor foo (var1 var2)
(a b c d e f g))
However, your program might not depend on a specific ordering of
components, because the components have no effect on each other.
For example, your program might depend only these ordering constraints:
- Flavor c must precede d.
- Flavor b must precede g.
- If flavor x is present (it could be a component of one of the
components, or it could be mixed into flavor foo to create a new
flavor), it must follow b and precede g.
You can specify those restrictions by giving the following option to defflavor:
(defflavor foo (var1 var2)
(a b c d e f g)
(:component-order (c d) (b x g)))
Note that this does not constrain flavors c and d to precede
flavors b, x, and g. Also, it is not an error to specify
an ordering constraint for a flavor that is not a component of this flavor.
For example, it is valid to constrain the order of x, although x
might not be a direct or indirect component of this flavor.
∂23-Feb-87 1941 Moon@STONY-BROOK.SCRC.Symbolics.COM errata sheet
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Feb 87 19:41:35 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 77255; Mon 23-Feb-87 22:41:37 EST
Date: Mon, 23 Feb 87 22:40 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: errata sheet
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 21 Feb 87 01:42 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870223224014.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 20 Feb 87 2242 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
I don't especially mind an errata sheet as long as it doesn't
contain un-agreed-to proposed re-wordings. The factual errors
are ok to put there, but I'd rather not see listed as errata an
inferior re-wording of a clearly worded paragraph. I don't mind
re-wording things if the re-wording is better, but good wording
is the result of long, careful thought.
I have a separate list of problems noticed in the document that I expect
to be controversial, which I do not plan to distribute publically. I
hope to mail it to this group in a few days for our own discussion.
I would be happy to move individual items that you disagree with on
the errata sheet into that other list instead, if you'll tell me
which ones they are, and if one round of discussion doesn't remove
the controversy. (I haven't finished studying Dick's earlier message
commenting on my draft errata sheet, and I haven't seen any comments
from anyone else yet.)
∂23-Feb-87 2206 edsel!bhopal!jonl@navajo.stanford.edu Relations to window standardization
Received: from NAVAJO.STANFORD.EDU by SAIL.STANFORD.EDU with TCP; 23 Feb 87 22:06:45 PST
Received: by navajo.stanford.edu; Mon, 23 Feb 87 22:05:30 PST
Received: from bhopal.edsel.com by edsel.uucp (2.2/SMI-2.0)
id AA01335; Mon, 23 Feb 87 17:46:32 pst
Received: by bhopal.edsel.com (3.2/SMI-3.2)
id AA12677; Mon, 23 Feb 87 17:43:59 PST
Date: Mon, 23 Feb 87 17:43:59 PST
From: edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)
Message-Id: <8702240143.AA12677@bhopal.edsel.com>
To: navajo!common-lisp-object-system%sail@navajo.stanford.edu
Subject: Relations to window standardization
Two messages recently appearing on the cl-windows mailing list:
Date: Fri, 20 Feb 87 23:43:36 PST
From: navajo!edsel!bhopal!jonl@navajo.stanford.edu (Jon L White)
To: navajo!Fahlman%C.CS.CMU.EDU@navajo.stanford.edu
Cc: navajo!cl-windows%SAIL@navajo.stanford.edu
In-Reply-To: "Scott E. Fahlman"'s message of Fri, 20 Feb 1987 22:45 EST
Subject: CW Standard Status
One possibility for standardization in the Common Lisp world is merely
on a user-interface to a window system. Having seen the sentiment on
this list, and others, it seems that folks clearly want
(1) some sort of object-oriented interface
(2) and one which doesn't require research-project-level effort
to understand and use.
I guess that is why the disussions often tie together a potential window
system candidate with an o-o candidate.
Let us very-hypothetically suppose that some o-o standard emerges within
the next year; then what do you think? can a reasonable subset of window
capability be described in o-o terms? This would not be the kind of
standard where everybody had to implement the features described in the
interface, or were restricted to it; but rather it would say "if you
provide capability Z, then the user interface to it should look like ....".
I'd expect that over time, there would come to be a certain minimum
set of required capabilities that everyone agreed would have to be
implemented in order for a candidate to call itself a window system.
I think we can rule out the ASR/35 and friends as being any part of
a "window" system.
-- JonL --
Date: Sun, 22 Feb 1987 20:42 EST
Sender: navajo!FAHLMAN@C.CS.CMU.EDU
From: "Scott E. Fahlman" <navajo!Fahlman@C.CS.CMU.EDU>
To: edsel!bhopal!jonl@λnavajo.stanford.eduλ (Jon L White)
Cc: cl-windows@SAIL.STANFORD.EDU
Subject: CW Standard Status
In-Reply-To: Msg of 21 Feb 1987 02:43-EST from edsel!bhopal!jonl at navajo.stanford.edu (Jon L White)
Sure, given an object-oriented standard, it's just a matter of figuring
out what higher-level abstractions are most appropriate and convenient
for a graphics/windows interface. If a consensus emerges about that,
then it's just a small matter of turning that consensus into a formal
standard. In order for this consensus to develop, we need some
experience, some good ideas, someone to work out a coherent proposal,
and someone to implement that proposal in reasonably portable
public-domain code.
I think that this may eventually happen. I don't know how long it will
take. Most of the groups I know about are just starting to experiment
with this stuff. Maybe there are segments of the Lisp community that
already have enough experience with objects and graphics to understand
what a really good set of abstractions would look like. If that same
set of people have the time and motivation to produce a proposal and
supporting code, then we could make very fast progress; if not, then
we're in for a couple of years of experimentation. If most of us can
work on a shared low-level substrate such as X, then the experimentation
will go more quickly because we can share what we develop.
-- Scott
∂25-Feb-87 1205 Moon@STONY-BROOK.SCRC.Symbolics.COM Proposed revision of "Inheritance of Slots and Slot Options" section
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 25 Feb 87 12:05:15 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 78684; Wed 25-Feb-87 13:38:11 EST
Date: Wed, 25 Feb 87 13:36 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Proposed revision of "Inheritance of Slots and Slot Options" section
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870225133647.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
The description of "Inheritance of Slots and Slot Options" is too
complex and too long. So far we have not been able to come up with a
description of this that is both precise and understandable. Because I
don't believe there is anything inherently complicated in the idea, I'm
making another attempt to write a description. To keep the terminology
consistent, I find I also have to change the section "Slots" on page
1-5. For readability I have removed all formatting controls; once we
have agreed on the wording the formatting controls can be restored.
\beginsubSection{Slots}
[first two paragraphs unchanged]
We say that a slot is defined by a class if the defclass form for that
class contains a slot specifier with the given slot's name.
[Metaclasses extend this idea, because they allow classes that aren't
defined by defclass, but I don't think we need to go into that here.
We could separate the ideas of "slot specifier" (source language syntax
found in defclass forms) and "slot description" (object found in data
structure, computed from a slot specifier), but that didn't seem to
add to understandability when I tried it, so I prefer not to introduce
slot descriptions until the meta-object chapter.]
We say that a slot is accessible in an instance of a class if the slot
is defined by the class of the instance or is inherited from a
superclass of that class. A detailed explanation of the inheritance of
slots is given in the section ``Inheritance of Slots and Slot Options.''
\beginsubSection{Inheritance of Slots and Slot Options}
The set of the names of all slots accessible in an instance of a class,
C, is the union of the sets of names of slots defined by C and its
superclasses. At most one slot of a given name can be accessible in an
instance.
In the simplest case, only one class in the class precedence list of C
defines a slot with a given slot name. If the class that defines the
slot is not C, we say that the slot is inherited. The characteristics
of the slot are determined by that class's slot specifier. If the
:allocation slot option is omitted or specifies a local slot, then each
instance of C stores its own value for the slot. If :allocation
specifies a shared slot, the class that defined the slot stores the
value and all instances of C access that single slot.
In general, more than one class in the class precedence list can define
a slot with a given name. In such cases, at most one slot with a given
name is accessible in an instance of C, and the characteristics of that
slot are a combination of the several slot specifiers, computed as
follows.
- All the slot specifiers for a given slot name are ordered
from most specific to least specific, according to the order of
the classes that define them in the class precedence list.
- The allocation of a slot is controlled by the most specific slot
specifier. If the most specific slot specifier does not contain
an :allocation slot option, :instance is used. Less specific slot
specifiers never affect the allocation.
- The initform of a slot is controlled by the most specific slot
specifier that contains an :initform slot option. If no slot specifier
contains an :initform, the slot has no default initial value form.
- The type of a slot is (and T1 T2 T3...), where T1, T2, T3, and so on
are the :type slot options contained in all of the slot specifiers. If
no slot specifier contains :type, the type is t.
A consequence of the allocation rule is that shared slots can be
shadowed. If a class C-sub-1 defines a shared slot named S, normally
that single slot is accessible in instances of C-sub-1 and all of its
subclasses. However, if C-sub-2 is a subclass of C-sub-1 and also
defines a slot named S, C-sub-1's slot is not shared by instances of
C-sub-2 and its subclasses. See S2 in the section ``Examples of
Inheritance.''
A consequence of the type rule is that the value of a slot must satisfy
the type constraint in -every- slot specifier that contributes to that
slot. This maximally restrictive rule allows a compiler to optimize on
the basis of the :type slot option. An argument to a method can be an
instance of a subclass of the class declared by a parameter specializer,
so the compiler cannot know the exact class.
Methods that access slots know only the name of the slot and the type of
the slot's value. Suppose a superclass provides a method that expects
to access a shared slot of a given name and a subclass defines a local
slot with the same name. If the method provided by the superclass is
used on an instance of the subclass, the method accesses the local slot.
The :reader and :accessor slot options were not mentioned above because
they create methods rather than defining characteristics of a slot.
Reader and accessor methods are inherited in the sense described in the
section ``Inheritance of Methods.''
[I also tried writing the above in notational form, in the spirit of
Dick's notation used in 87-002. However, with the new simplified
description the notation doesn't appear to add any understandability, so
I won't bother mailing it out. It's available on request.]
∂25-Feb-87 1458 Moon@STONY-BROOK.SCRC.Symbolics.COM Comments On Moon's Errata (Chapter 1 only)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 25 Feb 87 14:58:34 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 79019; Wed 25-Feb-87 17:59:06 EST
Date: Wed, 25 Feb 87 17:57 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Comments On Moon's Errata (Chapter 1 only)
To: Common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 19 Feb 87 17:22 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870225175739.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 19 Feb 87 1422 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Sorry about the slow response to these, I've been tied up with other things
the past few days.
Moon writes:
``1-11 fourth paragraph: Delete the entire paragraph, it isn't true....
I think the original statement is true, and it is because of that fact
that Moon's re-statement would be true. Possibly both statements should
be made, suitably phrased:
Because redefining a class does not change its name, the class $C\sub o$
does not have a name. Thus, writing a method for {\bf class-changed} that
is specialized to a particular $C\sub o$ must be done through the
functional interface, using {\bf add-method} rather than using {\bf
defmethod}. See the section ``Introduction to Methods.''
I think this might make the situation clearer to the reader.
I agree that this is better, except for one thing. The reason that C-sub-o does
not have a name is -not- because redefining a class does not change its name. For
example, in an earlier proposal from Xerox C-sub-o was given the name
(intern (concatenate 'string "obsolete-" (symbol-name (class-name class)))),
or something similar. This had a problem if the class was redefined twice,
but that could easily be fixed.
I put the following into my errata file, is this okay with everybody?
1-11 fourth paragraph: Delete the entire paragraph, it isn't true. Replace
it with this paragraph:
Because the class C-sub-O does not have a name, writing a method for
class-changed that is specialized to a particular C-sub-O
must be done through the functional interface, using add-method rather
than using defmethod. See the section ``Introduction to Methods.''
Moon writes:
``1-18 first paragraph under "Introduction to setf Generic Functions":
Change "(setf (generic-function-name arguments) new-value)"
to "(setf (function-name arguments) new-value)" because the base
function does not have to be generic, in fact it does not even have to
be defined.''
If this is correct, then it should be: ``(setf (symbol arguments)
new-value)''
Good point, I made that change in my file.
Moon writes:
``1-18 last paragraph: The term "parameter specifier" is used in a way that
is inconsistent with its use by CLtL and there are a couple of typographical
problems. Replace the entire paragraph with:
Each method has a {\bit specialized lambda-list}, which determines
when that method can be selected. A specialized lambda-list is like
an ordinary lambda-list except that a {\bit specialized parameter} may occur
instead of the name of a parameter. A specialized parameter is a list,
{\tt ({\it variable-name parameter-specializer-name\/})}. Every
parameter specializer name is a Common Lisp type specifier, but the only
Common Lisp type specifiers that are valid as parameter specializer names
are the following:''
The comment about bad use of ``parameter specifier'' is correct; I only
wish he had brought it up sooner.
I would have brought it up sooner if I had seen this edition of the
document sooner. The previous edition used "parameter specifier" in a way
that was consistent with CLtL.
I think the re-wording is not as good as
the original, though. We need to connect the linguistic item {\it
parameter-specializer-name} (typeset in italics) with an English phrase that
can be explained. The original had more information about the relationship
between parameter specializer names and Common Lisp type specifiers, and the
implicitness of that information in Moon's re-wording (and in earlier versions)
rendered the whole section incomprehensible.
I didn't think the phrase "where {\it parameter-specializer-name\/} is a
parameter specializer name" added anything to understandability. If you
strongly disagree we can put it back, but to me it seems unnecessary.
Aside from that, the only changes I made to the paragraph were to change
"parameter specifier" to "specialized parameter", removing a typo
("specializers" for "specializer"), and removing the portions of the
last two sentences that were redundant with the table at the top of
1-19. The explanation that quote and member are the same also appears
in the eighth paragraph on 1-19.
Here is a possible re-wording:
Each method has a {\bit specialized lambda-list}, which determines when
that method can be selected. A specialized lambda-list is like an
ordinary lambda-list except that a {\bit specialized parameter} may occur
instead of the name of a parameter. A specialized parameter is a list,
{\tt ({\it variable-name parameter-specializer-name\/})}, where {\it
parameter-specializer-name\/} is a parameter specializer name. Every
parameter specializer name is a Common Lisp type specifier, but the only
Common Lisp type specifiers that are parameter specializers names are type
specifier symbols with corresponding classes and type specifier lists of
the form {\tt ({\bf quote} {\it object})}. The form {\tt ({\bf quote} {\it
object})} is equivalent to the type specifier {\tt ({\bf member} {\it
object\/})}.
This undoes the changes I made, other than "parameter specifier" to
"specialized parameter". I really think that this would make it harder to
understand. Think about it again, and if you still disagree we can keep
discussing it, or strike this correction from the errata and do it later.
Moon writes:
``1-19 fourth paragraph, beginning "Only required parameters can be specialized":
The term "parameter specifier" is misused again. Replace the paragraph with:
Only required parameters can be specialized, and each required parameter
must have an associated parameter specializer. For notational simplicity,
ordinary lambda-list syntax can be used, that is, a parameter name can be
used instead of a specialized parameter. In this case the parameter
specializer defaults to the class named {\bf t}, the class of all objects.''
Again, the substantive point is well-taken, but the re-wording is bad.
The style has become flabby and imprecise. If you need to say ``that is,''
then you said the wrong thing in the first place. The paragraph is talking
about the required parameters, and the comment linking the syntax of them to
lambda-list syntax doesn't restrict the lambda-list syntax of interest to
the lambda-list syntax of required parameters. It is usually good to link
new concepts with old ones, but this wording simply confuses the issue.
Try this instead:
Only required parameters can be specialized, and each required parameter
must be a specialized parameter. For notational simplicity, if some
required parameter in a specialized lambda-list is simply a variable
name, the corresponding parameter specifier is taken to be {\tt
({\it variable-name} {\bf t})}.
This is better than what I suggested, but self-contradictory. First it
says that each required parameter must be a specializer parameter, which
was earlier defined as a list, then it says that a required parameter
can be a symbol. Also I have trouble figuring what is corresponding to
what when you say "corresponding". How about this wording?
Only required parameters can be specialized, and there must be a
parameter specializer for each required parameter. For notational
simplicity, if some required parameter in a specialized lambda-list is
simply a variable name, its parameter specializer defaults to the class
named {\bf t}.
Moon writes:
``1-19, seventh, eighth, and tenth paragraphs, discussing the relationship of
parameter specializers to type specifiers: Change "parameter specializer"
to "parameter specializer name" throughout these paragraphs, to be
consistent with the terminology used in earlier paragraphs.''
Nope. Moon missed the point, which, I guess, needs to be clarified even
more. The second paragraph on page 19 defines parameter specializers (PS)
in terms of parameter specializer names (PSN). The PSN's correspond to
names of classes while the PS's are the classes. ``Satisfaction'' operates
on the classes. This is so that the functional interface (ADD-METHOD et
al) can take PS's and DEFMETHOD can take PSN's. Otherwise we cannot
explain the change-class protocol.
I did not miss this point. Indeed, I thought that clarifying this distinction
substantially improved the document. Since I was only making an errata sheet
and since I didn't think you needed me to stroke your ego I left out
comments on the things that I thought were improved, and only commented
on the things that I thought were not good enough yet.
Read the offending paragraphs again. Paragraph 7 says
This proposal requires that parameter specializers also be Common Lisp
type specifiers.
and paragraph 8 says typep accepts parameter specializers. If this means that
typep is to be extended to accept class objects, that is a reasonable extension
to propose, however since it is mentioned nowhere else in the document and is
not stated explicitly here, and was never discussed on the mailing list,
I assumed that that was not the intention, and instead the problem was
that the conversion from "parameter specializer" to "parameter
specializer name" had not been carried out uniformly. So which is it?
If typep is to accept class objects, we need an errata entry that makes
that very explicit.
Later in paragraph 8 it says
Note that in general a
parameter specializer cannot be a type specifier list, such as {\tt
({\bf vector single-float})}.
which is true, but would make more sense to say of parameter specializer
names since that's what users write.
Paragraph 10 says
A method all of whose parameter specializers are {\bf t}...
but a parameter specializer cannot be t, only a parameter specializer name
can be t. This was the point that convinced me that all of these occurrences
of "parameter specializer" were typos for "parameter specializer name".
I'll think about the Chapter 2 comments later.
I look forward to your comments.
∂25-Feb-87 1944 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Meeting
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 25 Feb 87 19:43:54 PST
Received: from relay2.cs.net by RELAY.CS.NET id aa25849; 25 Feb 87 19:38 EST
Received: from ti-csl by csnet-relay.csnet id cb13175; 25 Feb 87 19:30 EST
Received: from dsg (juliett.ARPA) by tilde id AA16731; Tue, 24 Feb 87 08:18:23 cst
Received: From Jenner By dsg Via CHAOS-NET With CHAOS-MAIL; Tue, 24 Feb 87 08:18:39 CST
Message-Id: <2750163506-3742966@Jenner.ti-7>
Date: Tue, 24 Feb 87 08:18:26 CST
Sender: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Meeting
In-Reply-To: Msg of 20 Feb 87 2242 PST from Dick Gabriel <RPG@sail.stanford.edu>
Date: 20 Feb 87 2242 PST
From: Dick Gabriel <RPG@sail.stanford.edu>
I can make a meeting on monday, but I'd like to be within hailing
distance of the main meeting in case a fight breaks out.
Sounds good.
Patrick.
∂27-Feb-87 1626 Bobrow.pa@Xerox.COM Re: Proposed revision of "Inheritance of Slots and Slot
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 Feb 87 16:25:59 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 27 FEB 87 16:20:43 PST
Date: 27 Feb 87 16:20 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Proposed revision of "Inheritance of Slots and Slot
Options" section
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of NIL
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870227-162043-4596@Xerox>
I am now back from my trip so I will try to comment on some of the
relevant messages in my absence.
SLOT IHERITANCE
In general I agree with Moon that slot inheritance is simple and like
his rewording. A few minor glitches:
If the :allocation slot option is omitted or specifies a local
slot, then each instance of C stores its own value for the slot.
This needs to be specific about local being either :instance or :dynamic
(or perhaps it should have that earlier).
Secondly, the type constraint is presented very strongly. The intent of
having it (I pushed it in) was to allow compatibility with current
defstruct. Current defstruct does not specify that a slot MUST meet its
type constraint. Consequently, I would suggest that the rule specify:
"The :type of a slot need not be specified. If it is, the
interpretation is that the value of the slot should be of type (and T1
T2 T3...), where T1 , ... Tn are all the type specifiers provided in any
slot specifcation. Implementations need not check for values, but those
that do should use the interpretation, and hence may optimize for those
values."
And then one could add the following from Moon's suggestion.
A consequence of the type rule is that the value of a slot must
satisfy the type constraint in -every- slot specifier that
contributes to that slot. This maximally restrictive rule allows a
compiler to optimize on the basis of the :type slot option. An
argument to a method can be an instance of a subclass of the class
declared by a parameter specializer, so the compiler cannot know
the exact class.
danny
∂27-Feb-87 1824 RPG CPL
To: common-lisp-object-system@SAIL.STANFORD.EDU
Why not wait until X3J13 comments before we think about it further. We
should think in terms of people doing their own thing and extending DEFCLASS
accordingly.
-rpg-
∂27-Feb-87 1833 Bobrow.pa@Xerox.COM Re: CPL
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 Feb 87 18:33:41 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 27 FEB 87 18:31:58 PST
Date: 27 Feb 87 18:31 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: CPL
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 20 Feb 87
22:55 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870227-183158-4758@Xerox>
My worry is that most people, even after a lot of thought, will
think of it like this:
1. the CPL respects the superclass relationships
2. the CPL respects the order of direct superclasses
3. otherwise, it is a black box, and if the programmer doesn't
like it, he can supply his own.
I would hope that people would think more like (and we would present it
as):
1. the CPL respects the superclass relationships
2. the CPL respects the order of direct superclasses
3. the CPL keeps supers of superclasses together
4. classes appear only once in the CPL, as late as possible
For simple hierarchies, independent superclasses, and even simple joins
(last element of a superclass list is the only class that occurs more
than once), the CPL is simple to understand, i.e. left to right depth
first keeping the last occurrence of a class.
For complicated uses (not encouraged), where common supers occur in
non-last position, it is harder to satisfy these constraints (maybe
impossible). So there is a complicated algorithm. I won't worry about
it since I will never do these bad things (or will only think about the
constraints) rather than the list.
danny
∂27-Feb-87 2258 RPG Inheritance of Slots and Slot Options
To: Common-Lisp-object-system@SAIL.STANFORD.EDU
Moon's rewrite has some features of interest. Recall I don't claim that
what ended up in the draft is the last word, but it was meant to be
clear (at least) though not written as best it could be. I have a few minor
questions and comments about it:
Moon writes:
``We say that a slot is accessible in an instance of a class if the slot
is defined by the class of the instance or is inherited from a
superclass of that class. A detailed explanation of the inheritance of
slots is given in the section ``Inheritance of Slots and Slot Options.'' ''
He removed the sentence:
``At most, one slot of a given name can be accessible in an instance.''
Although he inserts it later, I think it doesn't hurt to leave it where
it is (as well).
Moon writes:
``- The type of a slot is (and T1 T2 T3...), where T1, T2, T3, and so on
are the :type slot options contained in all of the slot specifiers. If
no slot specifier contains :type, the type is t.''
Here I think the language is unclear. Does this mean that the :type option
for the most specific class is taken to be (and ...)? Is the slot
constrained to hold values that satisfy (and ...) in the sense that an
error is signaled if someone tries to store something there that does not
satisfy the type? The language we had originally stated that the :type
option defaulted to T, and the contents of the slot would always be of
type (and ...). This mimicked the language in CLtL for defstruct and
represents a statement more in line with types as optional information to
the compiler.
Later Moon writes:
``A consequence of the type rule is that the value of a slot must satisfy
the type constraint in -every- slot specifier that contributes to that
slot.''
The convention in CLtL is that the phrase ``x must do y'' means that
otherwise it is an error, so we can deduce that he means that the slot is
not constrained in the sense of signaling an error. We should probably
include at the beginning of these chapters a warning to read page 6 of
CLtL to understand the conventions of the language we use.
Moon writes in the next paragraph:
``An argument to a method can be an instance of a subclass of the class
declared by a parameter specializer, so the compiler cannot know the exact
class.''
This should be expanded because many will not easily see the connection
between random methods and optimizing based on the types of slots.
The strong type constraint rule Moon proposes has some effects that might
be difficult for a reader to understand unless explained properly. Suppose
we have:
(defclass c1 () ((foo :type t1)))
(defclass c2 (c1) ((foo :type t2)))
(defclass c3 (c1) ((foo :type t3)))
The FOO slot in C1 must be of type (and T1 T2) when regarded from the
point of view of C2, and it must be of the type (and T1 T3) when regarded
from the point of view of C3. Therefore, it actually must be of type
(and T1 T2 T3). The compiler compiling methods on C2 or C3 alone won't care
much, and when it compiles a method on C2 and C3 it might discover the happy
fact. A reader of this specification might be confused into thinking that
there is some intractable problem at hand and that the type of a slot cannot
actually be deduced because it depends on classes very far away.
Moon writes near the end:
``The :reader and :accessor slot options were not mentioned above because
they create methods rather than defining characteristics of a slot.
Reader and accessor methods are inherited in the sense described in the
section ``Inheritance of Methods.'' ''
This needs to be made clear at the outset: two-pass reading is bad
news.
-rpg-
∂28-Feb-87 0012 RPG Moon's Comments on RPG's Comments on Moon's Errata
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Moon comments:
``For example, in an earlier proposal from Xerox C-sub-o was given the
name (intern (concatenate 'string "obsolete-" (symbol-name (class-name
class)))), or something similar. This had a problem if the class was
redefined twice, but that could easily be fixed.''
Thank God this proposal went by the boards, though it is an excellent example
of why it's the case that the fewer things are named the better off we are.
Moon continues:
``I put the following into my errata file, is this okay with everybody?
``1-11 fourth paragraph: Delete the entire paragraph, it isn't true. Replace
it with this paragraph:
Because the class C-sub-O does not have a name, writing a method for
class-changed that is specialized to a particular C-sub-O
must be done through the functional interface, using add-method rather
than using defmethod. See the section ``Introduction to Methods.'' ''
This seems fine.
Moon writes:
``I didn't think the phrase "where {\it parameter-specializer-name\/} is a
parameter specializer name" added anything to understandability.''
If a reader has gotten used to meta-syntactic items being linked to
English phrases in a precise way, then failing to do that reduces
understandability.
How about this:
Each method has a {\bit specialized lambda-list}, which determines when
that method can be selected. A specialized lambda-list is like an
ordinary lambda-list except that a {\bit specialized parameter} may occur
instead of the name of a parameter. A specialized parameter is a list,
{\tt ({\it variable-name parameter-specializer-name\/})}, where {\it
parameter-specializer-name} is a parameter specializer name. Every
parameter specializer name is a Common Lisp type specifier, but the only
Common Lisp type specifiers that are valid as parameter specializer names
are the following:
This is Moon's rewrite with my pissant addition.
Moon writes:
``This is better than what I suggested, but self-contradictory. First it
says that each required parameter must be a specializer parameter, which
was earlier defined as a list, then it says that a required parameter
can be a symbol.''
Well, it actually said that the notation enabled a programmer to write a symbol
that would be taken as a specialized parameter, but Moon's rewriting is better
than what I had:
Only required parameters can be specialized, and there must be a
parameter specializer for each required parameter. For notational
simplicity, if some required parameter in a specialized lambda-list is
simply a variable name, its parameter specializer defaults to the class
named {\bf t}.
Moon correctly comments and asks:
``If this means that typep is to be extended to accept class objects, that is a
reasonable extension to propose, however since it is mentioned nowhere else in
the document and is not stated explicitly here, and was never discussed on the
mailing list, I assumed that that was not the intention, and instead the
problem was that the conversion from "parameter specializer" to "parameter
specializer name" had not been carried out uniformly. So which is it? If
typep is to accept class objects, we need an errata entry that makes that very
explicit.''
The class redefinition prose that Moon inserted into the document at some point
in time requires either that the prose talking about TYPEP at this point in the
document be removed or amended as I tried. I presumed that deleting content was
incorrect, so I tried to fix up this prose to be consistent. The offending
statement is ``the function TYPEP can be used to determine whether an argument
satisfies a parameter specializer.'' This statement is meant to reinforce the
fact that the class system extends the CL type system. If this statement is to
stand, TYPEP has to deal with class objects in addition to class names, because
of the functional interface.
More specifically, the issue is that MAKE-METHOD specifies class objects and
possibly TYPEP should be used during generic function invocation to
determine which methods are applicable. The class redefinition protocol
requires that we be able to write methods that apply to classes that have been
rendered obsolete (or nameless).
Here are the alternatives:
1. MAKE-METHOD takes class names; TYPEP operates on names and
type specifiers as usual (extended to classes); redefining
a class creates a stupid but predictable name for the ``old''
class (or we invent some funny notation to refer to obsolete
classes of various vintages).
2. MAKE-METHOD takes class objects; TYPEP is extended to class objects;
class redefinition renders the ``old'' class nameless.
3. We simplify the class redefinition protocol to eliminate
CLASS-CHANGED (this is the generic function that causes the
problem.
4. We can talk about how TYPEP can be used by the user to predict
which methods are applicable.
5. We can eliminate any statements about TYPEP.
I think 3. is not easily acceptable, because Moon's class redefinition protocol
is quite powerful (and suggestive to people trying to understand the system).
Option 2. probably will piss off the Common Lisp crowd. Option 3. will piss
me off. Option 4. is dumb. Option 5. requires some further changes to the
document to provide the function that really decides satisfaction.
Moon's further remarks on this point correctly indicate other problems that
can be easily solved once we decide whether we really intend that TYPEP
work on class objects.
I think I agreed with all of Moon's other errata. Moon: at some point (when we
all agree on the list) you should mail your current errata list to me.
-rpg-
∂28-Feb-87 0118 RPG Moon's Errata for Chapter 2
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Moon writes:
``2-5 Values paragraph: Replace the whole sentence with
"The value is {\it generic-function}." to clarify that the value
is EQ to the argument.''
We should agree on and adopt a means of stating that some function
destructively alters an argument, returning the altered thing as its
value. I'm not sure this suggestion accomplishes that best, but maybe it
does.
Moon writes:
``2-11 second Arguments paragraph: Delete the second sentence. It lost
its intended meaning as a result of previous editing.''
I'm not sure of this. I would agree to an argument that the paragraph
is hard to understand, but I think it stands on its own:
``When change-class is invoked on an instance, a copy [definition of the
`copy'] of that instance is made; change-class then destructively alters
the original instance [not the copy]. The first argument to
class-changed, previous, is that copy [reference to the `copy'], and the
second argument, current, is the altered original instance.''
Is this wrong? If it's unclear we can re-do it somehow.
Moon writes:
``2-11 first Remarks paragraph: Delete this. It contradicts an
example on page 2-8 and it isn't true.''
While he is literally correct, I think we need to reinforce somewhere in
this section that the functional interface must be used when classes are
redefined. This paragraph is the result of a hurry.
Moon writes:
``2-18 first bullet (:type). There is no discussion of the meaning and
enforcement of :type. Add the following (stolen from CLtL p.310):...''
This overlaps with the discussion about chapter 1. The language in chapter
1 has been variously vague on this also, but the version mailed to X3J13
also copied terminology from CLtL.
We minimally changed the DEFINE-METHOD-COMBINATION description due to lack
of time. It needs a major rewrite in addition to the comments Moon has about
it.
Moon writes a specific comment that requires a general policy answer:
``2-34 second paragraph...[This paragraph duplicates information found
elsewhere so perhaps it should be shortened.]''
In general I repeated information that I thought would puzzle readers.
Should we establish a convention of putting information on some topic
mostly in one place?
Moon writes:
``2-48 second Purpose paragraph: Delete "to the top level".''
Or change it to
``Whether ... or returns via THROW''
I don't like the terminology ``or throws.''
Moon writes:
``2-46 second Purpose paragraph first sentence: It was not intended to
guarantee that the returned value is a list with certain objects in its car
and cdr. Add the phrase "or a form with equivalent effect" at the end of
the sentence.''
Or maybe:
``The function {\bf make-method-call} returns a form whose effect is the
same as a form whose first element is the operator specified by the {\bf
:operator} keyword argument (the default is {\bf progn}) and the rest of
which is a list of forms that call the methods in the given method
list....''
Moon writes:
``2-47 Values paragraph: same as the preceding.
``2-48 second Purpose paragraph: Delete "to the top level".''
My earlier comments apply here, too.
Moon writes:
``2-53 last Arguments paragraph: Change "second" to "errorp".
Change (twice) "If there is no such method" to
"If {\it generic-function} does not know {\it method}".''
How about one of these:
``If {\it generic-function} does not perceive directly {\it method}.''
``If {\it generic-function} does not perceive or apprehend as
true {\it method}.''
``If {\it generic-function} does not have immediate experience of {\it
method}.''
``If {\it generic-function} has not been apprised of {\it method}.''
Abstract objects in a computer are not people, so we cannot use verbs
that apply to people to talk about them. Leave it as it is.
(I had to have fun somewhere in this message.)
-rpg-
∂28-Feb-87 0127 RPG All is Not Lost (?)
To: common-lisp-object-system@SAIL.STANFORD.EDU
I showed Chapter 1 to two people at Lucid who thought it was
very clear and well-written:
1. A mathematician with several theorems named after him.
2. A mathematician who got his PhD at age 19.
-rpg-
∂02-Mar-87 2234 Moon@STONY-BROOK.SCRC.Symbolics.COM Moon's comments on RPG's comments on Moon's Errata for Chapter 2
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 2 Mar 87 22:34:17 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 82864; Tue 3-Mar-87 01:34:47 EST
Date: Tue, 3 Mar 87 01:33 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Moon's comments on RPG's comments on Moon's Errata for Chapter 2
To: Common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 28 Feb 87 04:18 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870303013303.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 28 Feb 87 0118 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
[comments where I had nothing to add omitted for brevity]
Moon writes:
``2-11 second Arguments paragraph: Delete the second sentence. It lost
its intended meaning as a result of previous editing.''
I'm not sure of this. I would agree to an argument that the paragraph
is hard to understand, but I think it stands on its own:
``When change-class is invoked on an instance, a copy [definition of the
`copy'] of that instance is made; change-class then destructively alters
the original instance [not the copy]. The first argument to
class-changed, previous, is that copy [reference to the `copy'], and the
second argument, current, is the altered original instance.''
Is this wrong? If it's unclear we can re-do it somehow.
That's the first Arguments paragraph. I have no problems with it. I
was referring to the second Arguments paragraph, and suggesting removal
of "Any function, generic or not, can receive the value passed as
-previous- as an argument."
Moon writes:
``2-11 first Remarks paragraph: Delete this. It contradicts an
example on page 2-8 and it isn't true.''
While he is literally correct, I think we need to reinforce somewhere in
this section that the functional interface must be used when classes are
redefined. This paragraph is the result of a hurry.
I think we could leave that to the discussion of class redefinition in
chapter 1. I see it more as a property of the "obsolete" class than a
property of the class-changed generic function.
Moon writes a specific comment that requires a general policy answer:
``2-34 second paragraph...[This paragraph duplicates information found
elsewhere so perhaps it should be shortened.]''
In general I repeated information that I thought would puzzle readers.
Should we establish a convention of putting information on some topic
mostly in one place?
Either way is okay with me. I suggested shortening it because I thought that
would be easier than making the same corrections in more than one place.
Moon writes:
``2-48 second Purpose paragraph: Delete "to the top level".''
Or change it to
``Whether ... or returns via THROW''
I don't like the terminology ``or throws.''
That's better. I changed my draft errata file to read:
2-41 second Purpose paragraph: Replace it with "Whether
{\bf invalid-method-error} returns to its caller or exits
via {\bf throw} is implementation dependent."
2-48 second Purpose paragraph: Replace it with "Whether
{\bf method-combination-error} returns to its caller or exits
via {\bf throw} is implementation dependent."
Moon writes:
``2-46 second Purpose paragraph first sentence: It was not intended to
guarantee that the returned value is a list with certain objects in its car
and cdr. Add the phrase "or a form with equivalent effect" at the end of
the sentence.''
Or maybe:
``The function {\bf make-method-call} returns a form whose effect is the
same as a form whose first element is the operator specified by the {\bf
:operator} keyword argument (the default is {\bf progn}) and the rest of
which is a list of forms that call the methods in the given method
list....''
Yes, that's better. I put it into my draft errata file.
Moon writes:
``2-53 last Arguments paragraph: Change "second" to "errorp".
Change (twice) "If there is no such method" to
"If {\it generic-function} does not know {\it method}".''
How about one of these:
``If {\it generic-function} does not perceive directly {\it method}.''
``If {\it generic-function} does not perceive or apprehend as
true {\it method}.''
``If {\it generic-function} does not have immediate experience of {\it
method}.''
``If {\it generic-function} has not been apprised of {\it method}.''
Abstract objects in a computer are not people, so we cannot use verbs
that apply to people to talk about them. Leave it as it is.
(I had to have fun somewhere in this message.)
I guess we can't fix this nicely without terminology that comes from the
meta-object chapter. We should all have more fun. Should we make an
end run around the problem and simply remove the errorp argument and say
that remove-method never signals an error? Sort of like REMPROP, REMOVE,
and REMHASH.
∂03-Mar-87 0006 Moon@STONY-BROOK.SCRC.Symbolics.COM Moon's Comments on RPG's Comments on Moon's Errata
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 3 Mar 87 00:05:53 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 82921; Tue 3-Mar-87 03:06:30 EST
Date: Tue, 3 Mar 87 03:04 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Moon's Comments on RPG's Comments on Moon's Errata
To: Common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 28 Feb 87 03:12 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870303030444.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 28 Feb 87 0012 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
[comments where I had nothing more to add omitted for brevity]
Moon writes:
``I didn't think the phrase "where {\it parameter-specializer-name\/} is a
parameter specializer name" added anything to understandability.''
If a reader has gotten used to meta-syntactic items being linked to
English phrases in a precise way, then failing to do that reduces
understandability.
How about this:
Each method has a {\bit specialized lambda-list}, which determines when
that method can be selected. A specialized lambda-list is like an
ordinary lambda-list except that a {\bit specialized parameter} may occur
instead of the name of a parameter. A specialized parameter is a list,
{\tt ({\it variable-name parameter-specializer-name\/})}, where {\it
parameter-specializer-name} is a parameter specializer name. Every
parameter specializer name is a Common Lisp type specifier, but the only
Common Lisp type specifiers that are valid as parameter specializer names
are the following:
This is Moon's rewrite with my pissant addition.
OK, I put that into the draft errata file I am maintaining.
Moon correctly comments and asks:
``If this means that typep is to be extended to accept class objects, that is a
reasonable extension to propose, however since it is mentioned nowhere else in
the document and is not stated explicitly here, and was never discussed on the
mailing list, I assumed that that was not the intention, and instead the
problem was that the conversion from "parameter specializer" to "parameter
specializer name" had not been carried out uniformly. So which is it? If
typep is to accept class objects, we need an errata entry that makes that very
explicit.''
The class redefinition prose that Moon inserted into the document at some point
in time requires either that the prose talking about TYPEP at this point in the
document be removed or amended as I tried. I presumed that deleting content was
incorrect, so I tried to fix up this prose to be consistent. The offending
statement is ``the function TYPEP can be used to determine whether an argument
satisfies a parameter specializer.'' This statement is meant to reinforce the
fact that the class system extends the CL type system. If this statement is to
stand, TYPEP has to deal with class objects in addition to class names, because
of the functional interface.
More specifically, the issue is that MAKE-METHOD specifies class objects and
possibly TYPEP should be used during generic function invocation to
determine which methods are applicable. The class redefinition protocol
requires that we be able to write methods that apply to classes that have been
rendered obsolete (or nameless).
Of course there are other reasons as well to want anonymous classes.
Here are the alternatives:
1. MAKE-METHOD takes class names; TYPEP operates on names and
type specifiers as usual (extended to classes); redefining
a class creates a stupid but predictable name for the ``old''
class (or we invent some funny notation to refer to obsolete
classes of various vintages).
2. MAKE-METHOD takes class objects; TYPEP is extended to class objects;
class redefinition renders the ``old'' class nameless.
3. We simplify the class redefinition protocol to eliminate
CLASS-CHANGED (this is the generic function that causes the
problem.
4. We can talk about how TYPEP can be used by the user to predict
which methods are applicable.
5. We can eliminate any statements about TYPEP.
I think 3. is not easily acceptable, because Moon's class redefinition protocol
is quite powerful (and suggestive to people trying to understand the system).
Option 2. probably will piss off the Common Lisp crowd. Option 3. will piss
me off. Option 4. is dumb. Option 5. requires some further changes to the
document to provide the function that really decides satisfaction.
Moon's further remarks on this point correctly indicate other problems that
can be easily solved once we decide whether we really intend that TYPEP
work on class objects.
After thinking this over, I think #2 is the only alternative that will fly.
Perhaps this will give bozos something to yell about at the X3J13 meeting.
The only real problem I have with this is the anomaly that in parameter
specializers classes are represented by the objects themselves but "individuals"
are represented by funny little lists with QUOTE in the CAR. This doesn't
seem to generalize very well to other type-specifiers, should we want to
add them in the future. Would it be better to introduce pseudo-class objects
(obeying a subset of the protocol of classes; in particular, you cannot
instantiate them) for these parameter specializers? Or is it better to draw
a sharp boundary between real classes, which are full-scale objects, from
pseudo-class types, which are type-specifier lists?
Leaving that issue aside, I'd make the following amendments to the errata
to implement this suggestion. This is a first draft and might need some
cleaning up before letting the general public see it.
1-13 First paragraph: Delete the last sentence. Add a new paragraph at
the end of the page: "Every class that has a name has a corresponding
type with the same name as the class. In addition, every class object
is a valid type specifier. Thus (typep <object> <class>) is true if the
class of the given <object> is <class> itself or a subclass of <class>
and (subtypep <class1> <class2>) returns t t if <class1> is a subclass of
<class2> or they are the same class, and returns nil t otherwise."
1-19 seventh paragraph: Change to "This proposal requires that both
parameter specializers and parameter specializer names be Common Lisp
type specifiers."
[no substantive change here, this is just to avoid the possibility of
misinterpretation]
[no change any more to 1-19 eighth paragraph]
1-19 tenth paragraph: Change "parameter specializers are t" to
"parameter specializers are the class named t".
2-15 third paragraph: Add "A class object can be used directly as a
type-specifier. Thus (typep <object> <class>) is true if the class of the
given <object> is <class> itself or a subclass of <class>."
2-54: Add pages for SUBTYPEP, TYPE-OF, and TYPEP, explaining that
SUBTYPEP and TYPEP are to be extended to accept class objects as
type specifiers, and explaining that TYPE-OF never returns a
class object [is this right?], with a cross-reference to CLASS-OF.
I think I agreed with all of Moon's other errata. Moon: at some point (when we
all agree on the list) you should mail your current errata list to me.
Will do. Are you going to print up copies for the meeting or would you like
me to take care of that?
∂04-Mar-87 1502 Bobrow.pa@Xerox.COM Chapter 3
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Mar 87 15:02:21 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 04 MAR 87 13:31:07 PST
Date: 4 Mar 87 08:46 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Chapter 3
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870304-133107-1251@Xerox>
I am preparing the presentation for X3J13 of the metaobject material. I
would appreciate feedback on the chapter, even of the form of "this part
is good, but I don't see what that part is for" with specifics for this
and that. Of course, specific criticisms and/or suggestions for
improvements are even more welcome.
thanks
danny
∂04-Mar-87 1608 kempf%hplabsc@hplabs.HP.COM Re: Meeting
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 4 Mar 87 16:08:19 PST
Received: from hplabsc by hplabs.HP.COM with TCP ; Fri, 27 Feb 87 09:28:03 pst
Received: by hplabsc ; Fri, 27 Feb 87 09:27:21 pst
Date: Fri, 27 Feb 87 09:27:21 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8702271727.AA19940@hplabsc>
To: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET, RPG@SAIL.STANFORD.EDU
Subject: Re: Meeting
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
> Date: 20 Feb 87 2242 PST
> From: Dick Gabriel <RPG@sail.stanford.edu>
>
> I can make a meeting on monday, but I'd like to be within hailing
> distance of the main meeting in case a fight breaks out.
>
>Sounds good.
>
>Patrick.
>
Ok by me also.
Jim Kempf
∂04-Mar-87 1622 RPG Errata etc.
To: common-lisp-object-system@SAIL.STANFORD.EDU
Seems as though Moon and I begin to converge (!). LGD worked up
some macros to TEX of the errata in a pretty format. If Moon
were to send his errata to us, we will TEX and reproduce it for
the meeting. We'll need 2 - 3 days to do this to be safe.
-rpg-
∂04-Mar-87 1631 RPG Meeting Monday
To: common-lisp-object-system@SAIL.STANFORD.EDU
I have started the wheels churning for getting a meeting room
at the hotel for monday for the CLOS confab. I will reserve it
for all day, but we might only need part of it.
-rpg-
∂04-Mar-87 1703 kempf%hplabsc@hplabs.HP.COM Comments on 87-002, Chapter 1
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 4 Mar 87 17:01:34 PST
Received: from hplabsc by hplabs.HP.COM ; Mon, 23 Feb 87 11:36:39 pst
Received: by hplabsc ; Mon, 23 Feb 87 11:35:56 pst
Date: Mon, 23 Feb 87 11:35:56 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8702231935.AA19678@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Comments on 87-002, Chapter 1
Comments are listed in order of how important I think the problems with the document
are.
A) REDEFINING CLASSES
I have serious problems with this section. Coming at it from an implementor's
viewpoint, there are some potential portability holes (port holes? :-) ) in
the document that would be well to catch before they become cast in concrete.
Additionally, this section, in my opinion, slants the entire CLOS in the
direction of a prototyping vehicle rather than a vehicle for implementing
production code. I have nothing against prototyping, but the degree of
difficulty involved in engineering production code from the prototype
will ultimately determine whether anyone will use CLOS, since the objective
of most potential users is to deliver software products (unless the CLOS
is meant to be restricted to academic and research ends). Keep in mind
that I'm coming at this from a conventional architecture viewpoint.
To be specific, there are three points with which I take issue:
1) Paragraph 2, pg 1-11:
"Updating an instance does not change its identity as
defined by the EQ function"
Practically, this constrains instance implementations to use double indirect
referencing for slot access. Since most CL implementations will use pointer
equality for EQ, the requirement that instances must be updatable means that
some kind of base level storage block must be used to maintain EQ-ness, and
the slot values themselves must be stored in another, which can potentially
grow or shrink.
In fact, this requirement violates the whole concept of EQ-ness in Common
Lisp. From CLtL, pg. 78:
"Thus EQL tells whether two objects are *conceptually* the same,
whereas EQ tells whether two objects are *implementationally*
identical"
Changing the number of slots in a class, in fact, is changing the
instance implementation, since the size of the storage block
will change. Conceptually, the two classes are the same, since
they have the same name (one could argue even with this, I guess),
but clearly their instances are implemented differently, since
they have different numbers of slots.
2) The fact that instance updating can be done at all means serious
trouble for garbage collection. Since the CLOS needs somehow to
be able to find all instances of a class when the class is
incompatibly redefined, either pointers to the instances must
be kept around by the system or the entire heap must be searched
for instances when an update occurs. Presuming the latter is
a time-consuming operation (it need not be, if classes are kept in
different segments of the heap, sort of a modified BIBOP scheme,
but that has its own problems) the most efficient way would probably
be to keep track of pointers. However, if the system is holding
on to instances, they won't be forgotten when the user's code
forgets about them. This means that, without special modifications
to the garbage collector, forgotten instances will start clogging the
heap. One solution is "weak links", garbage collectable links which
the system forgets about when the user does, but these may be
difficult to implement on certain machines, or may involve much
overhead. Another is to treat user level access and update of variables
involving instances specially, so that the CLOS is notified when
the user forgets about something, but that would be putting overhead
into a process which should be fast. Finally, the user could be
required to notify the system when an instance is to be forgotten,
but that somehow doesn't fit well into the Common Lisp scheme
of things.
3) What happens to methods written on the old class? Do they
stop working? What if the methods contain a WITH-SLOTS and
some of the slots accessed within the scope of the WITH-SLOTS
disappear? Automatic instance updating would limit the amount
of optimization that could be done during a WITH-SLOTS expansion,
since changing the number of slots could invalidate any attempts
to directly access the slot values (like, for example, trying
to get rid of the double indirect referencing mentioned above).
What about accessor functions? Are they undefined? Redefined
to give an error?
4) Automatic instance updating, in and of itself, could have
potentially serious side effects in every day use.
Consider the following scenario. I am developing an application
within a programming environment written in CLOS. The environment
contains a class called TEXT-BUFFER, with a slot called CONTENTS.
While developing, I define a new TEXT-BUFFER class, but either
accidently or intentionally forget to include the CONTENTS slot.
As soon as I redefine the class, my environment is trashed, since
all the TEXT-BUFFER instances are redefined without CONTENTS.
Counter arguments to this are either "use the package system" or
"use another name for the class". But anyone who has developed
a large Common Lisp application can testify that packages and
naming are enough of a problem without adding this degree of
complexity. The potential for unpleasent suprises should cause
one to seriously reconsider automatic redefiniton, I think.
5) What, precisely, are the compile time semantics for class
changing (in fact, the entire document is vague on this subject
but more later)? If a class is being recompiled, is the
class redefined in the compile time environment? This could
potentially cause the compiler to break, if instances needed
for the compilation are updated automatically.
I would be particularly interested in hearing Garbial's comments
on this, since some of the problems I've outlined may be peculiar
to conventional architectures.
B) COMPILATION SEMANTICS
As mentioned above, there is no discussion of compilation semantics
in the document. There is a hook mentioned in 87-003 about a
compile time hash table for storing name-class associations during
compilation, but it is not clear in 87-002 what, if any, effect
this hook has on the default CLOS programmer interface. A whole
host of questions arise. Is it possible to define a class
and subclasses which inherit from it in a file and have things
work correctly? Are classes fully defined at compile time, and,
if so, will that cause the compilation environment to change
in a significant way? Can methods on a class be defined in
the same file as the class definition? Can methods on a
superclass be defined in the same file as methods on a
subclass and have optimizations for CALL-NEXT-METHOD work
correctly?
I should note that in several other object systems, making
inheritence work gracefully across seperate compilation
has been one of the hardest things to do. Objective-C,
for example, uses two text files to record inheritence
information, and this makes system building more complex.
C++ deliberately restricts how methods can be inherited
in order to avoid problems with seperate compilation.
In general, my feeling on this is that the CLOS should try
to stick to the Common Lisp goal of having the semantics
of compiled and interpreted code be identical. Additionally,
many complications can be avoided by side effecting the
compile time environment only when necessary. For example,
macros need to be defined in the compile time environment
so they get properly expanded into code being compiled,
so macro definition would seem to be a necessary side effect.
If users really want to have the compilation environment
side effected, they can always use (EVAL-WHEN (COMPILE) ...)
around the code to establish *compile time too* mode.
C) INTERACTION BETWEEN CLOS AND CL `DECLARE' AND `THE'
There is no mention in the document of how the CLOS will interact
with CL DECLARE and THE. The requirement that parameter specifiers
be type specifiers (pg. 1-19, paragraph 6) means that TYPEP
must do the right thing when given an instance object and
a valid class name (and presumably TYPEOF must return the class
name as well?) but does that mean I can say:
(DECLARE (TYPE TEXT-BUFFER X))
and:
(THE TEXT-BUFFER X)
CLtL is vague on what happens if I try to bind X to something
not of TYPE TEXT-BUFFER and I have it so DECLAREd (see pg. 158)
but more explicit for THE (pg. 161). And what happens if
I have two TEXT-BUFFER classes, one whose metaclass is
the default and one with metaclass COMMON-OBJECTS-CLASS?
Seems to me an additional set of declarations are needed,
one, perhaps, restricting the metaclass and one for
specifying that a variable name can be bound to an
object of a particular class *or a subclass*, since
the restriction to a single class is covered by TYPE.
This would allow implementations to optimize method lookup
away at compile time to varying degrees, potentially
completely for a TYPE declaration, and partially
for subclass and metaclass declarations.
D) PARTICULAR QUIBBLES
1) Pg. 1-5, paragraph 1. A reference to 87-003 (the metaobject chapter)
would probably be good here.
2) Pg. 1-6, paragraph 6. There is no statement anywhere in this section
or the next that a class cannot be defined with two slots having
the same name. Is this valid and, if so, how is access to be distinguished?
By different accessor function names? If so, which is used in WITH-SLOTS?
3) pg 1-7 through 1-9. The description of slot options, as Moon has
stated, seems needlessly complex. During the following, keep in mind
that I am coming at inheritence from the global viewpoint that subclasses
specialize behavior of superclasses. If that is kept in mind, I think
there are a number of ways to reduce the complexity. On to particulars:
a) pg. 1-7 paragraph 8:
"characteristics of that slot involve some combination of the several
slot descriptions"
I don't understand why it is necessary to have do this. Why not
simply use the class precedence list to determine which class
has highest priority and simply have the slot options for that
one dominate. Presumably, the user wants the highest precedence
class behavior to dominate, since it is the most specialized. If
that is not the case, then the slot option would, in my opinion,
be better off left as a method. The user can then redefine it
using CALL-NEXT-METHOD to get more general behavior.
b) The description of valid values on the top of the page has some notational
ambiguity. The first paragraph uses C(j) to indicate classes, but halfway
through the description on valid values, the notation uses the
syntax: (:CLASS j) to indicate that a class shares a shared slot. Did
you really mean that the user had to put a number indicating the
location of the class in the class precedence list? I think not.
c) At the bottom of the page, do you really want the default to be
UNSUPPLIED? If so, in what package is this symbol?
d) pg. 1-8. Middle bullet. Why use (AND T(1) .. T(n) )? Again, coming
at this from the point of view that subclasses specialize behavior
of supers, shouldn't the more specialized type prevail?
e) same page, last bullet. If there is no :INITFORM, then what happens
when the user tries to access the slot and it is not initialized?
In general, I think this particular bit needs to be worked out
in tandem with initialization in general, which has yet to be
specified.
4) pg 1-13 paragraph 2
"However, it is not allowed..."
I think the usual CLtL way of saying this is "an error is signalled." Also,
in paragraph 3, it sounds to me as if STRUCTURE-CLASS is actually a metaclass
is this so? Here would be a good place to have a figure illustrating the
top level metaclass/class structure which shadows the type system. Details
can be left to 87-002.2, but a figure would help conceptualization.
5) pg. 1-14-1-16. The inheritence algorithm. I actually thought this was
one of the best parts of the document (sorry Dick). It precisely specifies
how to calculate inheritence, and avoids some of the pitfalls and nasty
side effects that other multiple inheritence schemes seem to generate
(though I can't say I've examined it in lots of detail). However, it IS
poorly explained. In particular, some heuristic explanation of the role
R and S play in the algorithm would be useful. Also, on pg. 1-14, there
is a forward reference in paragraph 3, immediately after the definition
of R, to consistency, which leave the reader wondering what that is.
Also, I think the reference to topological sorting should be toned down
some, and the algorithm should rather be outlined stepwise instead of
as a paragraph. Finally, the example is OK, but there should be
examples of inconsistency as well. The single example given is trivial.
For my taste (no pun intended), the pie examples could very well be
be replaced by something more abstract, but not all readers may feel
this way.
6) pg. 1-19 after bullets:
"Let N be a parameter specializer name and P be the corresponding
parameter specializer; if N is a class name, then P is
the class with that name; otherwise N equals P."
This is unnecessarily confusing. Try:
"The method lookup process distingushes between parameter specializer
names and parameter specializers. If N is a parameter specializer
name and also the name of a class, then the corresponding parameter
specializer P will be the class named N."
The rest of this section has similar problems.
7) General comment on method combination. It is certainly clearer now
than in the original documents, but I wish the preciseness with
which the inheritence algorithm was specified could also be true
of method combination.
8) pg. 1-26. paragraph 1. Protocol point. In the list of other object
languages, why not include CommonObjects? As far as I know, it is
the ONLY language which has actually been implemented on top of
the metaobject protocol.
∂04-Mar-87 1803 Bobrow.pa@Xerox.COM Re: Meeting Monday
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Mar 87 18:03:25 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 04 MAR 87 17:09:09 PST
Date: 4 Mar 87 17:08 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Meeting Monday
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 04 Mar 87
16:31 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870304-170909-2070@Xerox>
I would like to spend a significant part of it discussing the
meta-object protocol. What else is on the agenda.
danny
∂04-Mar-87 1928 kempf%hplabsc@hplabs.HP.COM Re: Chapter 3
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 4 Mar 87 19:27:44 PST
Received: from hplabsc by hplabs.HP.COM with TCP ; Wed, 4 Mar 87 15:30:52 pst
Received: by hplabsc ; Wed, 4 Mar 87 15:29:30 pst
Date: Wed, 4 Mar 87 15:29:30 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8703042329.AA09807@hplabsc>
To: Bobrow.pa@Xerox.COM, Common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Chapter 3
At the risk of repeating myself, here is a note on Chapter 3 that
I posted last week. We have been having some problems with mail
delivery, and Danny's note has led me to believe this may not
have gotten delivered.
--------------------------------------------------------------------
I feel the major lack in this document is a clear statement of how one goes about
defining and implementing a new metaclass. What protocol does a class
need to support in order to be promotable to a metaclass via DEFINE-METACLASS?
Does DEFINE-METACLASS even care, i.e. does it check before promoting a class?
What types of slots? The answer to this question seems to be scattered about
the document, so this is more a criticism of organization than content.
An example defining a new metaclass would be helpful, but perhaps this document
is not the place for it, but rather a "User's Manual" type document might
be more appropriate.
As in the programmer interface document, a major technical problem is
lack of specification of compile time semantics. While the
:COMPILE-TIME-HASH-TABLE keyword argument to CLASS-NAMED-FROM-METACLASS
on pg. 3-14 provides a hook for maintaining information about partially
defined classes at compile time, no such hook exists for methods. To
give an example of how this can make implementation of a new metaclass
difficult, consider my experience with implementing inheritence of
methods in CommonObjects on CommonLoops (COOL). In COOL, CommonObjects
inheritence is maintained orthogonally to CommonLoops inheritence,
due to the nature of the encapsulation semantics specified by
CommonObjects. But COOL depends on the PCL kernel to obtain information
about what methods are defined on which classes (via CLASS-DIRECT-METHODS).
Where the interaction between these two factors becomes a problem is
in inheritence of methods. COOL determines at compile time what methods
a subclass inherits from its supers since it needs to generate special
code for inherited methods. However, the code generated
by PCL for methods doesn't fully define the method until load time,
as should be the case, since otherwise the compile time environment
could be detrimentally side effected. This means that a CommonObjects
super class and methods on the super class cannot be defined in the
same file as a subclass, since the superclass methods won't be fully
defined until load time and therefore won't be found during compilation
for the subclass to inherit.
To be fair, it would probably be possible to work around this problem
through more extensive redefinition of the method handling portion
of the PCL metaclass kernel, but it seems as if some means of maintaining
partially defined method information, as with classes, could be
designed to simplify implementing novel kinds of method inheritence.
Additional examples of where compile time semantics may cause problems
appear throughout the document. Consider the following description
of class precedence list calculation on pg. 3-4:
It is computed (just) before the first instance of this
class is created, or when any method is defined on this
class or any subclass.
What effect (if any) does compilation have on the class precedence
list? I can imagine cases where optimization of method lookup may
require knowing the class precedence list at compile time, and
where compilation of something may correspondingly cause the
class precedence list to change. This could even be true for
the default CLOS language; however, I think it is even more
important that compile time semantics get pinned down in the
metaobject protocol because the metaclass kernel is, in a
certain sense, a means of modifying the compiler/evaluator.
As a final point about the importance of nailing down compile
time semantics, consider the possibility of portability problems
developing. This is, in fact, currently the case with DEFSTRUCTs
in Kyoto Common Lisp. Unless *compile time too* mode is turned
on within KCL (the default), the SETF functions for DEFSTRUCT
accessors don't get generated at compile time, and hence SETF's
of DEFSTRUCT accessors don't expand properly. Turning on
*compile time too* mode causes an implicit (EVAL-WHEN (COMPILE) ...)
to be wrapped around the processing of top level forms, which can
cause serious problems with embedded languages (like PCL) that require
certain things (like full method definition) not get done at compile
time but rather only at load time. One solution to this problem
is simply to interpret the file before compiling, but that is
pushing the portability problem back into the system
building process.
Minor points of fuzziness within the document:
1) pg. 3-3. A figure of the inheritence/instance relationship
between the metaclass kernel classes would be most useful
here.
2) pg 3-6. The description of INITFORM. Is INITFORM run in the
context of a method? Is WITH-SLOTS valid within it? Again, as
with the CLOS language, this should probably be pinned down
along with the entire initialization protocol.
3) pg. 3-14. Description of SETF of class name. Does this go
both ways, i.e. if I (SETF CLASS-NAME) then will CLASS-NAMED
recognize the class under the new name? The last time I looked
in PCL, this was not the case (though it may have changed).
4) pg. 3-18. Description of FUNCTION slot in METHOD class.
Is this a fundef object (function pointer) or a symbol
whose function cell is bound?
5) Section 2.2. The description of the relationship between
the generic function classes and the method classes leaves
me somehow uneasy. While I can't make a case for having
one inherit from the other, it seems as if the relationship
should be more intimate than the generic function classes
simply having a slot for methods. Perhaps this can be
handled by using inheritence from one of the
generic function classes and having the SETF method
distinguish which methods get put onto the slot. I am
particularly concerned about having two co-existing
metaclasses and users trying to define methods on the
same symbol from both metaclasses. We currently handle
this in COOL by convention, i.e. telling users to
use PCL and COOL in the same package at their own risk.
6) pg. 3-21, and throughout the discussion of the
generic function classes. I somehow have the feeling that
having the generic function classes inherit from a
standard type class FUNCTION would more elegently tie
together the CLOS with Common Lisp, provided, of course,
the questions raised by the discussion on having a class
for FUCTION and the other types which were originally
not on the list to have classes can be answered.
∂05-Mar-87 0058 RPG Agenda
To: common-lisp-object-system@SAIL.STANFORD.EDU
I don't think there's any agenda. The meta-object protocol is as good as
anything else.
-rpg-
∂05-Mar-87 0740 kempf%hplabsc@hplabs.HP.COM Re: Meeting Monday
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 5 Mar 87 07:39:51 PST
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 5 Mar 87 07:39:42 pst
Received: by hplabsc ; Thu, 5 Mar 87 07:39:04 pst
Date: Thu, 5 Mar 87 07:39:04 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8703051539.AA15918@hplabsc>
To: Bobrow.pa@Xerox.COM, RPG@SAIL.STANFORD.EDU
Subject: Re: Meeting Monday
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
>I would like to spend a significant part of it discussing the
>meta-object protocol. What else is on the agenda.
> danny
>
Yes, that is an excellent idea. I also think that initialization,
change class, and inheritence of slot options should be on the
agenda, if possible. In the event there isn't enough time for
everything, my priorities for these three topics would be in
the order listed.
Jim Kempf
∂05-Mar-87 1158 kempf%hplabsc@hplabs.HP.COM 87-003 MetaObject Protocol
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 5 Mar 87 11:57:34 PST
Received: from hplabsc by hplabs.HP.COM ; Thu, 26 Feb 87 10:24:29 pst
Received: by hplabsc ; Thu, 26 Feb 87 10:24:01 pst
Date: Thu, 26 Feb 87 10:24:01 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8702261824.AA08020@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: 87-003 MetaObject Protocol
I feel the major lack in this document is a clear statement of how one goes about
defining and implementing a new metaclass. What protocol does a class
need to support in order to be promotable to a metaclass via DEFINE-METACLASS?
Does DEFINE-METACLASS even care, i.e. does it check before promoting a class?
What types of slots? The answer to this question seems to be scattered about
the document, so this is more a criticism of organization than content.
An example defining a new metaclass would be helpful, but perhaps this document
is not the place for it, but rather a "User's Manual" type document might
be more appropriate.
As in the programmer interface document, a major technical problem is
lack of specification of compile time semantics. While the
:COMPILE-TIME-HASH-TABLE keyword argument to CLASS-NAMED-FROM-METACLASS
on pg. 3-14 provides a hook for maintaining information about partially
defined classes at compile time, no such hook exists for methods. To
give an example of how this can make implementation of a new metaclass
difficult, consider my experience with implementing inheritence of
methods in CommonObjects on CommonLoops (COOL). In COOL, CommonObjects
inheritence is maintained orthogonally to CommonLoops inheritence,
due to the nature of the encapsulation semantics specified by
CommonObjects. But COOL depends on the PCL kernel to obtain information
about what methods are defined on which classes (via CLASS-DIRECT-METHODS).
Where the interaction between these two factors becomes a problem is
in inheritence of methods. COOL determines at compile time what methods
a subclass inherits from its supers since it needs to generate special
code for inherited methods. However, the code generated
by PCL for methods doesn't fully define the method until load time,
as should be the case, since otherwise the compile time environment
could be detrimentally side effected. This means that a CommonObjects
super class and methods on the super class cannot be defined in the
same file as a subclass, since the superclass methods won't be fully
defined until load time and therefore won't be found during compilation
for the subclass to inherit.
To be fair, it would probably be possible to work around this problem
through more extensive redefinition of the method handling portion
of the PCL metaclass kernel, but it seems as if some means of maintaining
partially defined method information, as with classes, could be
designed to simplify implementing novel kinds of method inheritence.
Additional examples of where compile time semantics may cause problems
appear throughout the document. Consider the following description
of class precedence list calculation on pg. 3-4:
It is computed (just) before the first instance of this
class is created, or when any method is defined on this
class or any subclass.
What effect (if any) does compilation have on the class precedence
list? I can imagine cases where optimization of method lookup may
require knowing the class precedence list at compile time, and
where compilation of something may correspondingly cause the
class precedence list to change. This could even be true for
the default CLOS language; however, I think it is even more
important that compile time semantics get pinned down in the
metaobject protocol because the metaclass kernel is, in a
certain sense, a means of modifying the compiler/evaluator.
As a final point about the importance of nailing down compile
time semantics, consider the possibility of portability problems
developing. This is, in fact, currently the case with DEFSTRUCTs
in Kyoto Common Lisp. Unless *compile time too* mode is turned
on within KCL (the default), the SETF functions for DEFSTRUCT
accessors don't get generated at compile time, and hence SETF's
of DEFSTRUCT accessors don't expand properly. Turning on
*compile time too* mode causes an implicit (EVAL-WHEN (COMPILE) ...)
to be wrapped around the processing of top level forms, which can
cause serious problems with embedded languages (like PCL) that require
certain things (like full method definition) not get done at compile
time but rather only at load time. One solution to this problem
is simply to interpret the file before compiling, but that is
pushing the portability problem back into the system
building process.
Minor points of fuzziness within the document:
1) pg. 3-3. A figure of the inheritence/instance relationship
between the metaclass kernel classes would be most useful
here.
2) pg 3-6. The description of INITFORM. Is INITFORM run in the
context of a method? Is WITH-SLOTS valid within it? Again, as
with the CLOS language, this should probably be pinned down
along with the entire initialization protocol.
3) pg. 3-14. Description of SETF of class name. Does this go
both ways, i.e. if I (SETF CLASS-NAME) then will CLASS-NAMED
recognize the class under the new name? The last time I looked
in PCL, this was not the case (though it may have changed).
4) pg. 3-18. Description of FUNCTION slot in METHOD class.
Is this a fundef object (function pointer) or a symbol
whose function cell is bound?
5) Section 2.2. The description of the relationship between
the generic function classes and the method classes leaves
me somehow uneasy. While I can't make a case for having
one inherit from the other, it seems as if the relationship
should be more intimate than the generic function classes
simply having a slot for methods. Perhaps this can be
handled by using inheritence from one of the
generic function classes and having the SETF method
distinguish which methods get put onto the slot. I am
particularly concerned about having two co-existing
metaclasses and users trying to define methods on the
same symbol from both metaclasses. We currently handle
this in COOL by convention, i.e. telling users to
use PCL and COOL in the same package at their own risk.
6) pg. 3-21, and throughout the discussion of the
generic function classes. I somehow have the feeling that
having the generic function classes inherit from a
standard type class FUNCTION would more elegently tie
together the CLOS with Common Lisp, provided, of course,
the questions raised by the discussion on having a class
for FUCTION and the other types which were originally
not on the list to have classes can be answered.
∂05-Mar-87 2311 RPG Kempf's Remarks
To: common-lisp-object-system@SAIL.STANFORD.EDU
Kempf makes some interesting remarks. I'm not sure I can answer
all of them, but Gregor and Moon can fill in the holes.
A. Redefining classes
1. I think that the big performance hit in double indirection
happens when the trampoline object that represents the identity
of the instance is on a different page from the storage for the
instance.
The issue of redefinition comes up whenever the programmer needs to
re-read a file of DEFCLASS's that are different. CLOS doesn't address,
yet, the issue of compiler declarations that static-ize the class
graph. Because there are ways of dealing with the issue of static
function linkages and reDEFUNition, there are ways of dealing
with this, also.
Thus, I think a ``sufficiently'' clever implementation can do ok,
but the question is how clever the implementor must be to produce this
implementation. It ought to be a topic of debate in a few weeks.
2. The section on class redefinition states that updating of instances
occurs in a lazy manner as instances are stumbled across. Therefore, there
is no need to keep sets containing them explicitly. Furthermore,
the blocks of storage for the new instances are created lazily at this
same time.
3. When a method is applied to an instance, that instance is updated
if a class redefinition has been done. So methods on the old instance
apply to the new instance, unless the methods have been implicitly removed
during class redefinition.
I think the document states that WITH-SLOTS might become confused when
classes are redefined.
4. No comment on this example.
5. I agree we should think about the issues of compilation semantics.
B) Compilation Semantics
I agree we need to think about these things.
C) Interaction between CLOS and CL ``THE'' and ``DECLARE''
I agree we have to think about this.
D) Particular Quibbles
Kempf writes:
``1) Pg. 1-5, paragraph 1. A reference to 87-003 (the metaobject chapter)
would probably be good here.''
When Chapter 3 is in good shape we need to have reasonable cross-references.
At the time that Chapters 1 and 2 were completed for X3J13, Chapter 3
was not available. I felt that it would not be reasonable to put references
in existing text to text that did not exist and was not known to be
guaranteed to ever exist.
Kempf writes:
``2) Pg. 1-6, paragraph 6. There is no statement ... that a class cannot
[have] two slots [with] the same name.''
This needs to be clarfied to state that there can only be one slot of a given
name.
Kempf writes:
``3) pg 1-7 through 1-9. The description of slot options, as Moon has
stated, seems needlessly complex.''
I agree that we can simplify this. When writing this section, there was
not enough time to thoroughly understand the slot description inheritance
rules and to think of how to explain them. Once I understood it, I wrote
up a correct, but dull and excessive, explanation that was correct so
that people could argue about its reasonableness. I didn't think it
was reasonable, so I had little enthusiasm to explain it well.
Kempf writes:
`` "characteristics of that slot involve some combination of the several
slot descriptions"
I don't understand why it is necessary to have do this.''
I think the main reason is that people will want to have only the incremental
updates to slot descriptions in each class definition. The `intuitively'
desirable behavior requires some defaulting where inheritance might seem
to make sense.
Kempf writes:
`` b) The description of valid values on the top of the page has some notational
ambiguity....''
Oh dear, this means that my meta-syntactic notation wasn't clear. The idea
was to define a mathematical abstraction that represented the semantics
of slot description inheritance. The definition of this abstraction was
meant to clarify the nature of combined slot descriptions. C(j) and (:class j)
were parts of this mathematical abstraction and hence is not intended to
exist anywhere. The funny numbers that Kempf refers to are simply the
part of the abstraction that represents the information about the class
with which a shared slot is shared.
Kempf continues:
`` c) At the bottom of the page, do you really want the default to be
UNSUPPLIED? If so, in what package is this symbol? ''
Again, this is part of the abstraction. When the part of the abstraction
corresponding to the initform is defined to be UNSUPPLIED this means that
in the slot description the effect is as if the initform were not supplied.
No package to think about here, except, possibly, PLATO-HEAVEN.
Kempf writes:
``d) pg. 1-8. Middle bullet. Why use (AND T(1) .. T(n) )? Again, coming
at this from the point of view that subclasses specialize behavior
of supers, shouldn't the more specialized type prevail?''
I don't understand this. The effect of the combined slot description
is as if the class definition contained (...:type T) and objects stored
in that slot will be (in DEFSTRUCT terminology) of type (and t(1) ... t(n))
where t(i) is the ith class in the CPL. Therefore, the type of object
is the specialized one Kempf desires (I think).
Kempf writes:
``7) General comment on method combination. It is certainly clearer now
than in the original documents, but I wish the preciseness with
which the inheritence algorithm was specified could also be true
of method combination. ''
Moon (and Sonya) spent some effort cleaning this section up. Nevertheless,
I judged it needed more rewriting, but I could not muster the enthusiasm
or time to do it myself. I had a hard enough time making sense of the
originally confusing uses of the terms ``primary method,'' ``auxiliary
method,'' and ``unqualified method.''
-rpg-
∂06-Mar-87 1902 Bobrow.pa@Xerox.COM Quote of the day
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Mar 87 19:02:49 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 06 MAR 87 18:39:03 PST
Date: 6 Mar 87 18:28 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Quote of the day
To: Common-lisp-object-system@SAIL.STANFORD.EDU
cc: Bobrow.pa@Xerox.COM
Reply-to: Bobrow.pa@Xerox.COM
Message-ID: <870306-183903-2496@Xerox>
A dedication for our work (or perhaps for the whole Common Lisp standardization effort).
From: Robert Hass "Praise" Ecco Press 1979
We asked the captain what course
of action he proposed to take toward
a beast so large, terrifying, and
unpredictable. He hesitated to
answer, and then said judiciously:
"I think I shall praise it."
Enjoy
danny
∂07-Mar-87 0114 a37078%ccut.u-tokyo.junet%utokyo-relay.csnet@RELAY.CS.NET Questions on CLOS specification
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 7 Mar 87 01:14:09 PST
Received: from relay2.cs.net by RELAY.CS.NET id aa05178; 7 Mar 87 4:13 EST
Received: from utokyo-relay by RELAY.CS.NET id aa14018; 7 Mar 87 4:05 EST
Received: by u-tokyo.junet (4.12/4.9J-1[JUNET-CSNET])
id AA04051; Sat, 7 Mar 87 10:30:42+0900
Received: by tansei.u-tokyo.junet (4.12/6.2Junet)
id AA14093; Sat, 7 Mar 87 01:08:05+0900
Date: Sat, 7 Mar 87 01:08:05+0900
From: Masayuki Ida <a37078%ccut.u-tokyo.junet%utokyo-relay.csnet@RELAY.CS.NET>
Return-Path: <a37078@ccut.u-tokyo.junet>
Message-Id: <8703061608.AA14093@tansei.u-tokyo.junet>
To: Common-lisp-object-system@SAIL.STANFORD.EDU,
ida%u-tokyo.junet@RELAY.CS.NET
Subject: Questions on CLOS specification
Questions and comments on Common Lisp Object System Specification
by Masayuki Ida, Japan
with the contributions of:
N. Saji (NEC), Yokoo (NTT), Ohkubo (panaFacom), Shiota (Nippon Symbolics),
Kawabe (Nippon UNIVAC), Nishida (Fuji Xerox)
Basically We are welcome to have an object system for Common Lisp.
Though we have no more experience to read the CLOS Specification,
we send this mail to CL-Object-system bboard as our first impression memo
I hope it may assist the discussion on the comming meeting at Palo Alto.
1>> make-specializable
PCL has a make-specializable. How can we add method for a Common Lisp
function.
(defmethod print ...) give us a special procedure to handle special case
on print in PCL.
2>> initialization protocol of make-instance
Page 1-5 says "The initialization protocol of make-instance is not yet specified."
It seems to arise many difficulties if the initialization protocol
will not be specified. We recommend meta object protocol should be included.
observation : there is no :initable-instance-variable thing of Flavors
in CLOS.
:init qualifier of Flavors is not included. So, we need meta object.
3>> defrecord
Where is defrecord syntax ?
4>> allocation slot option
there is no :none allocation
:none allocation allows us to eliminate the not-needed inherited slots allocation.
We prefer :none be included
5>> allocation option 2
there seems to be a :dynamic allocation.
But there is no explanation on :dynamic.
6>> page 1-6 Accessing Slots
"The macro with-slots can be used to set up a lexical environment in which
certain slots are lexically available"
What is the definition of 'lexical environment' in this context ?
it only says the slot name shadows the same name symbol if any ?
7>> page 1-7 Inheritance of Slots and Slot options
there is no story on :dynamic
:instnce story contains the story for :dynamic ?
8>> page 1-8 Ti can be a Common Lisp Type
Why does a class NOT allowed to be a :type ?
If we can write a class name for a :type, with the assistance of metaclass
idea, we can do more interest things like active-value with simple
extension.
9>>page 1-9 7L (and T1 ... Tn)
It is too severe restriction on type.
10>> Examples of Inheritance
what is the intension of the example ?
11>> Redefining Classes : Slot renaming
Is it possible to rename the slot ?
class-changed enable it ?
Is it truely possible ?
Accessor for old-name is safely deleted if w can rename slot by class-changed ?
12>> Redefining Classes : change-class
Is it possible to go to a quite different class ?
If it is OK to go to a quite different class,
a type-conversion may occur for the same slot with different types
between the old and the new ?
the intention of change-class is like the become: of smalltalk ?
become: plays a role to grow the instance, but we feel
change-class have a more flexible power ?
13>> Page 1-13 Integrating Types and Classes
How about the following story ?
split types into three categolies
1) Essential types; which are the terminal types just above the nil type.
they will be the defined most-specific types.
2) Defined types; which are the types defined in CLtl except Essential types.
3) system dependent types; which are the types defined in the specific
implementation
It is not allowed for the value of class-of to be a type of 3).
The system must return the type of Essential types if the object belong to
the type upon class-of invocation.
14>> Page 1-14 'require'
"We require that an implementation of Common Lisp Object System signal an
error if R is inconsistent,..."
What the word 'require' mean in this case ?
15>> Page 1-15 Examples ; the sequence of defclasses
(defclass pie (apple cinnamon) ())
appeared first. It means apple and cinnamon definitions are NOT needed prior to defclassing pie ?
16>> Page 1-17 Local generic function
Are there any true possibility to have a local (lexical) generic functions ?
There was a discussion on mlet thing.Mlet will revival ?
17>> individual method with unreadable object
Is it possible to QUOTE unreadable object on defmethoding ?
Say, can we write a trap routine which is invoked upon the access to specific memory location ?
18>> we feel (not ..) and (or ..) syntax for defmethod parameter-specializer-name should be included.
(defmethod foo ((x (or symbol simple-string character))) ...)
(defmethod foo ((x (not null))) ...)
19>> Page 1-20 Congruent Lambda-lists
Consider the following three cases.
1) the case where we need to have a method specifying the classes for optional parameter
(defmethod foo ((x foo)(y bar) &optional z) ...)
(defmethod foo ((x foo)(y bar) (z baz) &optional zz) ...)
2) generic operation concept with different numbers of arguments.
(defmethod rotate ((x 2d-position)(theata number)) ...)
(defmethod rotate ((x 3d-position)(theata number)(rou number)) ...)
3) extending the current methods to new methods with more arguments.
OLD (defmethod foo ((x ...) (y ...)) ...)
->
NEW (defmethod foo ((x ...)(y ...)(z ...)) ...)
there will be a transient status where the two argument version and
three argument version co-exist.
We feel the congruence should get to be more loose.
20>> call-next-method
call-next-method has no arguments.
Then the arguments are from the lambda list of the current method.
this means the arguments can be modified before call-next-method ?
The modified value are passed to the next-method ?
21>> add-method
the first argument is preferable to be a name,not a generic function object
itself. But we also understand the add-method is generic function itself,
so, it is not possible to write a name for the first argument.
Is it impossible to define add-method as a function ?
22>> Page 2-9 5L
is it allowed to supply :x 2 :y 0 without initable declaration or something ?
there is no concept of inittable decralation ?
23>> Page 2-11 class-changed
Remarks says "It is not possible to define methods on class-changed by using defmethod"
But Page 2-8 example uses defmethod to define class-changed ?
24>> Page 2-16 class-option
there is no initable related option ?
25>> Page 2-50 multiple-value-prog2
why multiple-value-prog2 is included as a part of CLOS ?
it should goto more general discussion ?
(I know multiple-value-prog2 is used in define-method-combination)
∂08-Mar-87 0253 kempf%hplabsc@hplabs.HP.COM Re: Consistency
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 8 Mar 87 02:53:23 PST
Received: from hplabsc by hplabs.HP.COM ; Fri, 20 Feb 87 08:37:02 pst
Received: by hplabsc ; Fri, 20 Feb 87 08:36:28 pst
Date: Fri, 20 Feb 87 08:36:28 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8702201636.AA19092@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Consistency
In response to Gabrial's concerns:
>At this point I'm worried about a couple of new things: first, that
>the Common-Lisp-skeptics will accuse us of doing to object-oriented
>programming what we did to Lisp: obfuscate and ruin it;
This may happen, but I think it is too late to back out now.
Application developers are waiting for an object oriented extension,
and there has been some grumbling that if a major application written
in Common Lisp (NOT an expert system shell) does not come out in
the next year or so, Common Lisp, itself, may be sunk.
> second, that
>the proposal might be in jeopardy because it is too complex.
Though this may sound trite, I think the quote from Einstein about
"everything should be made as simple as possible to understand,
but not simpler" is relevent here. If we are trying to do something
complex, then we should try to explain it as simply as possible.
If there is too much mechanism, then maybe some should be eliminated.
As I have not had a chance to look at the documents yet (scheduled
for this weekend) I can't yet say which may be the case.
>The people at Tektronix had no trouble understanding what I said, nor
>did they fail to understand CLOS. They were appalled at the complexity
>and questioned whether that complexity was necessary.
I think some of the complexity may be the result of a desire to
provide maximum flexibility. Certainly this is true of the
Metaobject Kernel.
>I still believe that we are writing a specification, and it would be wrong
>to put fluffy, imprecise language into the document. I think from my
>comments about Moon's errata you can still see this attitude. And if you
>compared the draft material as of 2 weeks ago with the current draft you
>will see a major movement towards consistency and preciseness, even at the
>expense of pretty language - it may not be perfect, but a lot of
>what was there before was embarrassingly bad.
>
>When I decide to write things using mathematical notation, for example, it
>is because I cannot think of how to unambiguously express the concepts in
>English. (Also, if the concepts were simpler, they could be expressed in
>prose more easily.)
I think there is a major problem here which CLtL itself faces, and
that is specifications of large complex software systems just simply
cannot be done accurately in English (or any other natural languge,
for that matter). Nobody expects to be able to built a bridge or
a jet airplane from an English description, why should the
same not be true of a complex software system? Specification
languages like Larch or OBJ are the only way to get a precise
design, in my opinion, but they are still largely experimental,
and therefore probably of little help to the task at hand.
As mentioned, I have yet to read the documents, but from my
experience working with PCL over the last couple months,
I think there is something worthwhile there and I would
not like to see it remain unavailable to applications developers
because some people are grumbling.
Jim Kempf kempf@hplabs.hp.com
∂08-Mar-87 0342 kempf%hplabsc@hplabs.HP.COM Comments on CLOS specification
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 8 Mar 87 03:42:00 PST
Received: from hplabsc by hplabs.HP.COM ; Mon, 23 Feb 87 11:35:42 pst
Received: by hplabsc ; Mon, 23 Feb 87 11:35:04 pst
Date: Mon, 23 Feb 87 11:35:04 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8702231935.AA19657@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Comments on CLOS specification
So far, I've read through the Introduction and MetaObject Protocol
chapters. I'll post my comments on each section individually.
Jim Kempf kempf@hplabs.hp.com
∂09-Mar-87 1122 RPG Meeting
To: common-lisp-object-system@SAIL.STANFORD.EDU
I have a meeting room at the hotel reserved for 9-5 Monday.
Because I will possibly need to flame at the regular meeting
during the Cleanup Committee discussion, I'd like to start
our meeting early in the day. Is 9am ok with everyone?
-rpg-
∂10-Mar-87 1114 DLW@ALDERAAN.SCRC.Symbolics.COM Meeting
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 10 Mar 87 11:13:44 PST
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 60354; Tue 10-Mar-87 13:58:36 EST
Date: Tue, 10 Mar 87 13:57 EST
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Meeting
To: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 9 Mar 87 14:22 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870310135741.7.DLW@CHICOPEE.SCRC.Symbolics.COM>
9am is fine with me. (That's noon eastern time...)
∂10-Mar-87 2001 Bobrow.pa@Xerox.COM Re: Meeting
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Mar 87 20:01:08 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 10 MAR 87 17:09:07 PST
Date: 10 Mar 87 17:08 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Meeting
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 09 Mar 87
11:22 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870310-170907-204@Xerox>
9am Fine.
danny
∂10-Mar-87 2116 Moon@STONY-BROOK.SCRC.Symbolics.COM Inheritance of Slots and Slot Options
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 10 Mar 87 21:15:57 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 90130; Wed 11-Mar-87 00:08:27 EST
Date: Wed, 11 Mar 87 00:08 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Inheritance of Slots and Slot Options
To: Common-Lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 28 Feb 87 01:58 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870311000821.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 27 Feb 87 2258 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
He removed the sentence:
``At most, one slot of a given name can be accessible in an instance.''
Although he inserts it later, I think it doesn't hurt to leave it where
it is (as well).
I put it back, in the revised errata I am about to mail out.
Moon writes:
``- The type of a slot is (and T1 T2 T3...), where T1, T2, T3, and so on
are the :type slot options contained in all of the slot specifiers. If
no slot specifier contains :type, the type is t.''
Here I think the language is unclear. Does this mean that the :type option
for the most specific class is taken to be (and ...)? Is the slot
constrained to hold values that satisfy (and ...) in the sense that an
error is signaled if someone tries to store something there that does not
satisfy the type? The language we had originally stated that the :type
option defaulted to T, and the contents of the slot would always be of
type (and ...). This mimicked the language in CLtL for defstruct and
represents a statement more in line with types as optional information to
the compiler.
The errata sheet already contains a description of what the :type slot
option means, based on earlier discussion over the mail. What may be
confusing is that it's buried in the description of defclass in chapter 2.
I don't see a really good place to put it in chapter 1.
Later Moon writes:
``A consequence of the type rule is that the value of a slot must satisfy
the type constraint in -every- slot specifier that contributes to that
slot.''
The convention in CLtL is that the phrase ``x must do y'' means that
otherwise it is an error, so we can deduce that he means that the slot is
not constrained in the sense of signaling an error.
Again, this is explained in chapter 2. In the revised errata sheet I am
about to mail out, I changed the wording of the offending sentence to be
clearer.
We should probably
include at the beginning of these chapters a warning to read page 6 of
CLtL to understand the conventions of the language we use.
I agree, it wouldn't hurt to say that we are using the same terminology
as CLtL in the next version of this document.
Moon writes in the next paragraph:
``An argument to a method can be an instance of a subclass of the class
declared by a parameter specializer, so the compiler cannot know the exact
class.''
This should be expanded because many will not easily see the connection
between random methods and optimizing based on the types of slots.
Instead, I removed the whole discussion. It seems either a whole page of
design rationale is needed here, or it's better simply to state how it is
without trying to explain why.
The strong type constraint rule Moon proposes
Please note that I never proposed this, I only tried to make the explanation
understandable. If I had my druthers, there would be no :type slot option.
has some effects that might
be difficult for a reader to understand unless explained properly. Suppose
we have:
(defclass c1 () ((foo :type t1)))
(defclass c2 (c1) ((foo :type t2)))
(defclass c3 (c1) ((foo :type t3)))
The FOO slot in C1 must be of type (and T1 T2) when regarded from the
point of view of C2, and it must be of the type (and T1 T3) when regarded
from the point of view of C3. Therefore, it actually must be of type
(and T1 T2 T3). The compiler compiling methods on C2 or C3 alone won't care
much, and when it compiles a method on C2 and C3 it might discover the happy
fact. A reader of this specification might be confused into thinking that
there is some intractable problem at hand and that the type of a slot cannot
actually be deduced because it depends on classes very far away.
Your last sentence here was what really convinced me that it was better not to
try to explain the design rationale here. I removed all mention of compilers.
Moon writes near the end:
``The :reader and :accessor slot options were not mentioned above because
they create methods rather than defining characteristics of a slot.
Reader and accessor methods are inherited in the sense described in the
section ``Inheritance of Methods.'' ''
This needs to be made clear at the outset: two-pass reading is bad
news.
I agree; I moved this up to a more appropriate place.
∂10-Mar-87 2137 Moon@STONY-BROOK.SCRC.Symbolics.COM 87-002 errata
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 10 Mar 87 21:35:50 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 90146; Wed 11-Mar-87 00:26:55 EST
Date: Wed, 11 Mar 87 00:26 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: 87-002 errata
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870311002649.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Here is the errata sheet for the 87-002 document, revised on the
basis of all the discussion over the mail. Dick and Linda have
graciously offered to format this and print up copies to
distribute at the X3J13 meeting. I imagine there is still a day
or so to remove or correct anything that is not generally agreed
upon (I tried to do so already); the exact amount of time depends
on their schedule.
1-4 seventh paragraph: The distinguished class T is mentioned but its
characteristics are not described in the document, except by
implication. Add the sentence:
T has no superclasses and is a superclass of every class except itself.
1-5 at the end of the ``Defining Classes'' section, add "A class
definition cannot contain two slot specifiers with the same name."
1-5 first paragraph under ``Slots'': Replace the first sentence with
"An object has zero or more named slots. An object's set of slots
is determined by the object's class. Each slot can hold one value."
1-6 first paragraph: Change ":instance" to ":instance or :dynamic".
1-6 second and third paragraphs: Replace them with the following:
We say that a class {\it defines\/} a slot with a given name
when the {\bf defclass} form for that class contains a slot
specifier with that name. Defining a local slot does not
immediately create a slot; it causes a slot to be created each
time an instance of the class is created. Defining a shared slot
creates a slot.
We say that a slot is {\it accessible\/} in an instance of a
class if the slot is defined by the class of the instance or
is inherited from a superclass of that class. At most one slot
of a given name can be accessible in an instance.
A detailed explanation of the inheritance of slots is
given in the section ``Inheritance of Slots and Slot Options.''
1-6 last paragraph: At the end of the second sentence: change "lexically
available" to "lexically available as if they were variables".
1-7: Replace the section ``Inheritance of Slots and Slot Options'' with
the new section supplied below.
1-10: Replace the last sentence with "There is also a method
for {\bf setf} of {\tt C2-S3} that writes the value of {\tt S3}."
1-11 second paragraph: The vague word "access" is used without definition.
Add the sentence: "In this context, an instance is said to be
accessed when a generic function is called with the instance as an
argument that is used for method selection, or when {\bf slot-value}
is called with the instance as its first argument."
1-11 third paragraph: Remove the sentence "The function {\bf change-class}
is called when the number of instance variables changes or when the name of
any instance variable changes" since there is no such concept as "instance
variable" in this standard. Replace it with the sentence:
"When a class is redefined in such a way that the set of local slots
accessible to an instance of the class is changed, or the order of slots
in storage is changed, updating an instance of the class calls the function
{\bf change-class}."
1-11 fourth paragraph: Delete the entire paragraph, it isn't true. Replace
it with this paragraph:
Because the class C-sub-O does not have a name, writing a method for
class-changed that is specialized to a particular C-sub-O
must be done through the functional interface, using add-method rather
than using defmethod. See the section ``Introduction to Methods.''
1-11 fifth paragraph third sentence: Change "Each slot of the new version"
to "Each local slot of the new version". Last sentence: Delete "For
local slots," since we are only talking about local slots anyway.
1-11 last paragraph: Change "the value of that slot will be the same
in both instances" to "the value of that slot is unchanged". Since only
one instance is involved, we can't say "both instances."
1-11 last paragraph: Break the paragraph after the third sentence so local
slots and shared slots are discussed in separate paragraphs. Clarify that
the paragraph discussing shared slots refers to what happens at the time
the class is redefined, and shared slots are not affected by updating an
instance nor by the values of local slots.
1-12 last paragraph: Change "Whether {\bf defclass} is allowed to change
the metaclass" to "Whether {\bf defclass} is allowed to change the
metaclass, and whether redefining a class updates existing instances,".
1-13 First paragraph: Delete the last sentence. Add a new paragraph at
the end of the page: "Every class that has a name has a corresponding
type with the same name as the class. In addition, every class object
is a valid type specifier. Thus (typep <object> <class>) is true if the
class of the given <object> is <class> itself or a subclass of <class>
and (subtypep <class1> <class2>) returns t t if <class1> is a subclass of
<class2> or they are the same class, and returns nil t otherwise."
1-18 first paragraph under "Introduction to setf Generic Functions":
Change "(setf (generic-function-name arguments) new-value)"
to "(setf (symbol arguments) new-value)" because the base
function does not have to be generic, in fact it does not even have to
be defined.
1-18 last paragraph: The term "parameter specifier" is used in a way that
is inconsistent with its use by CLtL and there are a couple of typographical
problems. Replace the entire paragraph with:
Each method has a {\bit specialized lambda-list}, which determines
when that method can be selected. A specialized lambda-list is like
an ordinary lambda-list except that a {\bit specialized parameter} may occur
instead of the name of a parameter. A specialized parameter is a list,
{\tt ({\it variable-name parameter-specializer-name\/})}, where {\it
parameter-specializer-name} is a parameter specializer name. Every
parameter specializer name is a Common Lisp type specifier, but the only
Common Lisp type specifiers that are valid as parameter specializer names
are the following:
1-19: Delete the first line "In short..." since the two bulleted items are
now introduced by the preceding paragraph.
1-19 fourth paragraph, beginning "Only required parameters can be specialized":
The term "parameter specifier" is misused again. Replace the paragraph with:
Only required parameters can be specialized, and there must be a
parameter specializer for each required parameter. For notational
simplicity, if some required parameter in a specialized lambda-list is
simply a variable name, its parameter specializer defaults to the class
named {\bf t}.
1-19 fifth paragraph: Change "when the class of each required argument"
to "when each required argument".
1-19 seventh paragraph: Change to "This proposal requires that both
parameter specializers and parameter specializer names be Common Lisp
type specifiers."
1-19 tenth paragraph: Change "parameter specializers are t" to
"parameter specializers are the class named t". Change "always part of
the generic function" to "always applicable".
1-19 last paragraph fourth sentence: Change "cons" to "list".
1-22 second paragraph: Change "the specializers must be quoted objects
(otherwise" to "the specializers must be equal (otherwise".
1-23 first line: Change "defmacro" to "defmethod".
1-25 sixth paragraph: Change "All {\bf :around} methods run before any
primary methods run." to "All {\bf :around} methods run before any
non-{\bf :around} methods run."
1-26 first paragraph: Change "Flavors" to "CommonObjects".
2-5 Values paragraph: Replace the whole sentence with
"The value is {\it generic-function}." to clarify that the value
is EQ to the argument.
2-8 Purpose paragraph: Add the sentences "The generic function
{\bf change-class} is invoked automatically by the system after
{\bf defclass} has been used to redefine an existing class.
It can also be explicitly invoked by the user."
2-8 Values paragraph: Replace the whole sentence with
"The value is {\it instance}." to clarify that the value
is EQ to the argument.
2-11 Purpose paragraph: Delete the sentences "The generic function
{\bf change-class} is invoked automatically by the system after
{\bf defclass} has been used to redefine an existing class.
It can also be explicitly invoked by the user." Add the sentence
"The function {\bf class-changed} is called only by
the function {\bf change-class}."
2-11 second Arguments paragraph: Delete the second sentence. It lost
its intended meaning as a result of previous editing.
2-11 first Remarks paragraph: Delete this. It contradicts an
example on page 2-8 and it isn't true.
2-11 second Remarks paragraph: Some occurrences of change-class should be
class-changed and there are a couple of terminological problems ("copy",
"part"). Replace the paragraph with:
The arguments to {\bf class-changed} are computed by {\bf change-class}.
The first argument is an instance of the original class
created to hold the old slot values temporarily.
This argument has dynamic extent within {\bf class-changed},
and therefore it is an error to reference it in any way
once {\bf class-changed} returns.
2-15 third paragraph: Add "A class object can be used directly as a
type-specifier. Thus (typep <object> <class>) is true if the class of the
given <object> is <class> itself or a subclass of <class>."
2-15 last line: Delete this. Defclass has no effect on the value cells
of symbols.
2-17 second paragraph: Delete ", from their superclasses, and so on".
2-17 :allocation bullet: Change "in the class instance" to "in each
instance".
2-18 first bullet (:type). There is no discussion of the meaning and
enforcement of :type. Add the following (stolen from CLtL p.310):
This specifies that the contents of the slot will always be of the
specified data type. This is entirely analogous to the declaration of a
variable or function; indeed, it effectively declares the result type of
the reader generic function when applied to an object of this class. An
implementation may or may not choose to check the type of the new value
when initializing or assigning to a slot.
2-18 :accessor-prefix, :reader-prefix bullets: Change "These ... functions
are interned" to "These ... function names are interned".
2-26 short-form-option syntax: Delete the :order clause.
2-27 fourth bullet: Delete it.
2-29 first paragraph: Replace the next to last sentence with: "If {\bf
:description} is not specified, a default description is generated based on
the variable name and the qualifier patterns, and on whether this
method-group includes the unqualified methods."
2-33 third paragraph: Change "If no generic function is currently named by
the symbol {\it name\/}" to "If {\tt (fboundp {\it name\/})} is {\bf nil}"
to match the terminology used on page 2-21.
2-34 first paragraph: Change "primary (in this case, unqualified) methods"
to "unqualified methods".
2-34 second paragraph: Same problem with "parameter specifier" as on 1-18.
Replace the first two sentences of the paragraph with:
The {\it specialized-lambda-list\/} argument is like an ordinary function
lambda-list except that required parameter names can be replaced by
specialized parameters. A specialized parameter is a list of the form
{\tt ({\it variable-name parameter-specializer-name\/})}.
2-35 syntax for specialized-setf-lambda-list: Change "specializer" to
"parameter-specializer-name".
2-38 fourth Arguments paragraph: Change "If the first argument is a symbol"
to "If the first argument is a symbol that names a class".
2-38 last Arguments paragraph: Change "If the first argument is a symbol"
to "If the first argument is a symbol that has a setf generic function
associated with it".
2-39 last Arguments paragraph: Change "second" to "errorp".
2-41 second Purpose paragraph: Replace it with "Whether
{\bf invalid-method-error} returns to its caller or exits
via {\bf throw} is implementation dependent."
2-46 second Purpose paragraph first sentence: It was not intended to
guarantee that the returned value is a list with certain objects in its
car and cdr. Change "a form whose first element" to "a form whose
effect is the same as a form whose first element".
2-47 Values paragraph: same as the preceding.
2-48 second Purpose paragraph: Replace it with "Whether
{\bf method-combination-error} returns to its caller or exits
via {\bf throw} is implementation dependent."
2-53 Syntax paragraph: remove "&optional errorp".
2-53 last Arguments paragraph: Replace the entire paragraph with
"{\bf remove-method} does not signal an error if the method has
already been removed from the generic function."
2-53 Values paragraph: Replace the whole sentence with
"The value is {\it generic-function}." to clarify that the value
is EQ to the argument.
2-54: Add pages for SUBTYPEP, TYPE-OF, and TYPEP, explaining that
SUBTYPEP and TYPEP are to be extended to accept class objects as
type specifiers, and explaining that TYPE-OF never returns a
class object, with a cross-reference to CLASS-OF. (Unresolved
issue: does TYPE-OF an instance of an anonymous class return the
class object, or does it return some symbol?)
2-55 last paragraph first sentence: Delete "or a superclass".
2-55 last paragraph fourth sentence: Change "not a subclass of the
specified class" to "not the specified class or a subclass of the
specified class".
2-55 last paragraph fifth sentence: Change "superclass of the instance" to
"superclass of the actual class of the instance" and change "different"
to "smaller".
2-56 second paragraph: Change "using the accessor function" to "calling the
accessor function", "is used to access" to "is called to access", and
"accesses the slots by using" to "accesses the slots by calling".
2-56 Values paragraph: Change "value" to "values" to clarify that the
body can return multiple values.
!
Revised ``Inheritance of Slots and Slot Options'' section:
[For readability all TEX formatting has been temporarily removed]
The set of the names of all slots accessible in an instance of a class,
C, is the union of the sets of names of slots defined by C and its
superclasses. At most one slot of a given name can be accessible in an
instance.
In the simplest case, only one class among C and its superclasses
defines a slot with a given slot name. If the class that defines the
slot is not C, we say that the slot is inherited. The characteristics
of the slot are determined by the slot specifier of the defining class.
If the :allocation slot option is omitted, :instance, or :dynamic, then
it specifies a local slot and each instance of C has its own slot that
stores its own value. If the :allocation slot option is :class, then it
specifies a shared slot, the class that defined the slot stores the
value, and all instances of C access that single slot.
In general, more than one class among C and its superclasses can define
a slot with a given name. In such cases, only one slot with the given
name is accessible in an instance of C, and the characteristics of that
slot are a combination of the several slot specifiers, computed as
follows.
- All the slot specifiers for a given slot name are ordered
from most specific to least specific, according to the order in
the class precedence list of C of the classes that define them.
- The allocation of a slot is controlled by the most specific slot
specifier. If the most specific slot specifier does not contain
an :allocation slot option, :instance is used. Less specific slot
specifiers never affect the allocation.
- The initform of a slot is controlled by the most specific slot
specifier that contains an :initform slot option. If no slot specifier
contains an :initform, the slot has no default initial value form.
- The type of a slot is (and T1 T2 T3...), where T1, T2, T3, and so on
are the :type slot options contained in all of the slot specifiers. If
no slot specifier contains :type, the type is t.
The :reader and :accessor slot options were not mentioned because
they create methods, rather than defining characteristics of a slot.
Reader and accessor methods are inherited in the sense described in the
section ``Inheritance of Methods.''
A consequence of the allocation rule is that shared slots can be
shadowed. If a class C-sub-1 defines a shared slot named S, normally
that single slot is accessible in instances of C-sub-1 and all of its
subclasses. However, if C-sub-2 is a subclass of C-sub-1 and also
defines a slot named S, C-sub-1's slot is not shared by instances of
C-sub-2 and its subclasses. See S2 in the section ``Examples of
Inheritance.''
A consequence of the type rule is that the value of a slot satisfies the
type constraint of each slot specifier that contributes to that slot.
Note that an implementation may or may not choose to check the type of
the new value when initializing or assigning to a slot.
Methods that access slots know only the name of the slot and the type of
the slot's value. Suppose a superclass provides a method that expects
to access a shared slot of a given name and a subclass defines a local
slot with the same name. If the method provided by the superclass is
used on an instance of the subclass, the method accesses the local slot.
∂10-Mar-87 2116 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Proposed revision of "Inheritance of Slots and Slot
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 10 Mar 87 21:16:06 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 90132; Wed 11-Mar-87 00:10:25 EST
Date: Wed, 11 Mar 87 00:10 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Proposed revision of "Inheritance of Slots and Slot
Options" section
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870227-162043-4596@Xerox>
Message-ID: <870311001020.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 27 Feb 87 16:20 PST
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
In general I agree with Moon that slot inheritance is simple and like
his rewording. A few minor glitches:
If the :allocation slot option is omitted or specifies a local
slot, then each instance of C stores its own value for the slot.
This needs to be specific about local being either :instance or :dynamic
(or perhaps it should have that earlier).
An earlier item on the errata sheet was to add :dynamic where it had been
left out. But I agree that it's better to mention the specific keywords
here too, so I added that to the revised errata sheet I am about to mail
out.
Secondly, the type constraint is presented very strongly. The intent of
having it (I pushed it in) was to allow compatibility with current
defstruct. Current defstruct does not specify that a slot MUST meet its
type constraint. Consequently, I would suggest that the rule specify:
"The :type of a slot need not be specified. If it is, the
interpretation is that the value of the slot should be of type (and T1
T2 T3...), where T1 , ... Tn are all the type specifiers provided in any
slot specifcation. Implementations need not check for values, but those
that do should use the interpretation, and hence may optimize for those
values."
In 87-002 it seems we forgot to say anywhere what :type really means.
The errata sheet for chapter 2 says something that I think is equivalent
to what you just said.
∂11-Mar-87 0006 kempf%hplabsc@hplabs.HP.COM Re: Gabriel's Comments
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 11 Mar 87 00:05:35 PST
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 10 Mar 87 12:18:00 pst
Received: by hplabsc ; Tue, 10 Mar 87 09:31:52 pst
Date: Tue, 10 Mar 87 09:31:52 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8703101731.AA00849@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Gabriel's Comments
Sorry it's taken so long to get around to this. Starting from
the bottom up, here's some replies to Dick's comments:
METHOD COMBINATION
>``7) General comment on method combination. It is certainly clearer now
>than in the original documents, but I wish the preciseness with
>which the inheritence algorithm was specified could also be true
>of method combination. ''
>
>Moon (and Sonya) spent some effort cleaning this section up. Nevertheless,
>I judged it needed more rewriting, but I could not muster the enthusiasm
>or time to do it myself. I had a hard enough time making sense of the
>originally confusing uses of the terms ``primary method,'' ``auxiliary
>method,'' and ``unqualified method.''
>
I think my problems with the section had nothing to do with its casting
in English, but rather with a general dissatisfaction with using
English to describe something so complicated. As there doesn't seem
to be much choice of a more precise language at the moment, I think
the current version looks OK.
CLASS REDEFINITION
With regard to class redefinition, lazy update would certainly get
rid of having to keep pointers around in classes, but would introduce
an extra operation during method dispatch, slot access, or whatever
operation was chosen to do the update. Since method dispatch is
100% overhead as far as the applications programmer is concerned,
the question is whether the added flexibility of having the class
update automatically is worth the extra time spent checking during
method dispatch. Similarly with slot access.
Note that inserting update into dispatch could also interfere
with staticizing a class. Suppose you have finished developing
a class and now want to staticize it. If method dispatches must
check whether instances need to be changed, staticization needs
not only to affect classes but also methods dispatching on the
classes, since the check for changes in the class must be removed
from the dispatch.
Problems with WITH-SLOTS and with inadvertent trashing of important
classes ala` the example with TEXT-BUFFER remain to be solved.
In addition, the question of whether changing a class definition
and having instances still be EQ is consistent with Common Lisp's
EQ semantics needs to be resolved.
INHERITANCE OF SLOT DESCRIPTORS
Due to problems with our mail delivery, my note got delivered
after Moon's simpilified slot descriptors note, although it
was mailed before. So I hadn't had a chance to look at it.
It looks to have simplified a good portion of the explanation,
but it would be useful to see it in context.
I think I understand the logic behind (AND ...) type specifiers
for inherited slots with the :TYPE option now, after some more
study. I think the desired specialization is being achieved with
this.
∂11-Mar-87 0701 Bobrow.pa@Xerox.COM Re: Inheritance of Slots and Slot Options
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Mar 87 07:01:51 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 11 MAR 87 07:01:08 PST
Date: 11 Mar 87 07:01 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Inheritance of Slots and Slot Options
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 11 Mar 87 00:08 EST
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870311-070108-1469@Xerox>
The strong type constraint rule Moon proposes
Please note that I never proposed this, I only tried to make
the explanation understandable. If I had my druthers, there would
be no :type slot option.
As the one who proposed the :type option (because I was trying to be
upward compatible from defstruct), I support Moon's feeling. If this is
uniformly the case (Dick, we have not heard from you on this issue),
then why don't we delete it. It is something that can be added with the
metaobject protocol.
Proposal. In the errata sheet we eliminate :type, and make an explicit
statement to that effect in the presentation.
danny
∂11-Mar-87 0800 Bobrow.pa@Xerox.COM Re: Gabriel's Comments
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Mar 87 07:59:51 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 11 MAR 87 07:57:10 PST
Date: 11 Mar 87 07:56 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Gabriel's Comments
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Tue,
10 Mar 87 09:31:52 pst
To: kempf%hplabsc@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870311-075710-1512@Xerox>
With regard to class redefinition, lazy update would certainly
get rid of having to keep pointers around in classes, but would
introduce an extra operation during method dispatch, slot access,
or whatever operation was chosen to do the update. Since method
dispatch is 100% overhead as far as the applications programmer is
concerned, the question is whether the added flexibility of having
the class update automatically is worth the extra time spent
checking during method dispatch. Similarly with slot access.
Note that inserting update into dispatch could also interfere
with staticizing a class. Suppose you have finished developing a
class and now want to staticize it. If method dispatches must check
whether instances need to be changed, staticization needs not only
to affect classes but also methods dispatching on the classes,
since the check for changes in the class must be removed from the
dispatch.
The issue you bring up here can be characterized in terms of a tradeoff
between a good development environment and one fully optimized for
speed. I assume that when you talk of "staticizing a class" you really
mean "staticizing a set of classes and generic functions which apply
only to those classes". And that the former means that you expect not
to build any subclasses of the staticized classes (or at least have them
staticized immediately). The purpose of the meta-object protocol in
part is to allow you to change the implementation of a set of classes by
defining the implementation structure, and optimizations of slot access
and method lookup. For classes of such metaclasses, neither
CHANGE-CLASS nor instance updating (CLASS REDEFINITION) need work.
These are only guaranteed to work for STANDARD-CLASS.
In addition, the question of whether changing a class
definition and having instances still be EQ is consistent with
Common Lisp's EQ semantics needs to be resolved.
It is the same semantics as EQ when a list structure has been RPLAC'd.
EQ implies a continuity of history and coreference.
danny
∂11-Mar-87 0913 RPG Inheritance of Slots
To: common-lisp-object-system@SAIL.STANFORD.EDU
I think we should leave in the :type descriptor. Since none of
you care about it, let be commune with my compiler and propose
a reasonable thing, which will probably be a variant of what
is currently in the spcification.
While we're on the topic of deriding parts of the specification that only
one person likes, I'd like to re-propose flushing :dynamic slots. Now let
me see, what kind of convincing argument can I give? Hm, could it be ``it
is something that can be added with the metaobject protocol''?
-rpg-
∂11-Mar-87 0939 RPG Staticizing
To: common-lisp-object-system@SAIL.STANFORD.EDU
Kempf rightly points out that this is a concern. I thought I had a scheme
to do it similar to the scheme for staticizing function calls, but I'm now
not entirely sure of it. I hope to rethink it today, but for the moment,
Kempf, suffice it to say I am sympathetic to your concerns.
Danny, we cannot relegate all matters to the metaobject protocol, though
we could. If we want to start putting things there that are now in the
first-order specification, I have a long list.
-rpg-
∂11-Mar-87 1306 skeene@STONY-BROOK.SCRC.Symbolics.COM Glossary (enclosed)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Mar 87 13:04:52 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 90789; Wed 11-Mar-87 16:04:27 EST
Date: Wed, 11 Mar 87 16:04 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Glossary (enclosed)
To: rpg@sail.stanford.edu, lgd@sail.stanford.edu
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870311160408.0.SKEENE@JUNCO.SCRC.Symbolics.COM>
The Glossary would be helpful for the X3J13 audience. I've written one
up, by taking the definitions out of the text of the document, mostly
verbatim. In case you want to see where the definition came from, the
list below shows the page number of each definition.
Would you format the Glossary and have it copied in time for next week's
meeting? Please also write it to the standard places in the CLS,LSP
directory. I would do so myself, if only I knew the password.
-----------------------
Page References in CLOS Document for Glossary Entries
:after method 1-24
:around method 1-24
:before method 1-24
accessor 1-6
applicable method 1-21
auxiliary method 1-20
class 1-3
class precedence list 1-4
declarative method combination 1-25
default method 1-19 and Errata
direct subclass 1-4
direct superclass 1-4
effective method 1-21
generic function 1-3
instance 1-3
local precedence order 1-4
local slot 1-6
metaclass 1-4
method 1-3
method combination
parameter specializer 1-18, 1-19
parameter specializer name 1-18, 1-19
primary method 1-20
qualified method 1-19
qualifier 1-19
qualifiers 1-18
reader 1-6
setf generic functions 1-18 and Errata
setf methods 1-18 and Errata
shared slot 1-6
slot 1-5 and Errata
slot description 1-7, 2-17
slot specifier 1-7, 2-17
specialized lambda list 1-18 and Errata
standard method combination 1-26
standard-class 1-26
standard-generic-function 1-26
standard-type-class 1-26
structure-class 1-26
subclass 1-4
superclass 1-4
unqualified method 1-19
-----------------------------------------------------
\input macros
\def\bookline{\CLOS\ Specification}
\def\chapline{Glossary}
\beginChapter 4.{Common Lisp Object System Specification}%
{Glossary}{Glossary}
\endTitlePage
\beginSection{Introduction}
The terminology is introduced in this document the first time each term
is used. This section presents the terms in alphabetical order, for
easy reference.
\endSection%{Introduction}
\beginSection{Glossary}
{\bit Accessible slot\/}:
We say that a slot is accessible in an instance of a
class if the slot is defined by the class of the instance or
is inherited from a superclass of that class. At most one slot
of a given name can be accessible in an instance.
{\bit Accessor\/}:
When a slot has an accessor, this means it has two generic functions,
one for reading the value of the slot, and another for writing the value
of the slot. The mechanism for writing is to use {\bf setf} with the
reader generic function. {\bf defclass} has options for automatically
generating methods for slot accessors; these methods are implemented by
using {\bf slot-value} and are added to the appropriate generic
functions. It is possible to modify the behavior of these generic
functions by writing methods for them.
{\bit :after method\/}:
In standard method combination, an {\bf :after} method has the keyword
{\bf :after} as its only qualifier. An {\bf :after} method specifies
code that is to be run after the primary method.
{\bit Applicable method\/}:
Given a generic function and a set of arguments, the applicable methods
are all methods for that generic function whose parameter specializers
are satisfied by their corresponding arguments.
{\bit :around method\/}:
In standard method combination, an {\bf :around} method has the keyword
{\bf :around} as its only qualifier.
{\bit Auxiliary method\/}:
In standard method combination, a qualified method has the role of
auxiliary method; an auxiliary method modifies the main action of the
effective method in some way. Standard method combination allows zero
qualifiers or a single qualifier, which is one of: {\bf :after}, {\bf
:before}, or {\bf :around}.
{\bit :before method\/}:
In standard method combination, a {\bf :before} method has the keyword
{\bf :before} as its only qualifier. A {\bf :before} method specifies
code that is to be run before the primary method.
{\bit Class\/}:
An object that describes the structure and behavior of a set of objects,
which are called its instances. Every Lisp object is an instance of a
class, and can be queried for its class by using the {\bf class-of}
function. The class of an object determines the set of
operations that can be performed on the object. {\bf defclass} is
used to define new classes.
{\bit Class precedence list\/}:
A total ordering of the set of the given class and its superclasses.
The total ordering is expressed as a list ordered from most specific to
least specific. The class precedence list is used in several ways.
The method selection and combination process uses the class precedence
list to order methods from most specific to least specific. Similarly,
the process of determining slot characteristics uses the class
precedence list to order slot specifiers from most specific to least
specific.
{\bit Declarative method combination\/}:
The programmer can use the {\bf define-method-combination} macro to
define new forms of method combination. The method-combination type
controls the selection of methods, the order in which they are run, and
the values that are returned by the generic function.
There are two forms of {\bf define-method-combination}. The short form
is a simple facility for the cases that have been found to be most
commonly needed. The long form is more powerful but more verbose; it
allows arbitrary control structures to be implemented, and arbitrary
processing of method qualifiers.
{\bit Default method\/}:
A method all of whose parameter specializers are the class named {\bf t}
is a default method. Note that if a parameter has no specializer, it
is the same as having a parameter specializer of {\bf t}, since {\bf t}
is the class of all objects. A default method is always applicable, but
is often shadowed by a more specific method.
{\bit Defining a slot\/}:
We say that a class {\it defines\/} a slot with a given name
when the {\bf defclass} form for that class contains a slot
specifier with that name. Defining a local slot does not
immediately create a slot; it causes a slot to be created each
time an instance of the class is created. Defining a shared slot
creates a slot.
{\bit Direct superclass and subclass\/}:
The direct superclasses of a class are those classes that are included
explicitly in the superclass list in the {\bf defclass} form. Class A
is a direct subclass of class B if B is a direct superclass of A.
{\bit Effective method\/}:
When a generic function is called with particular arguments, it must
decide what code to execute. We call this code the effective method for
those arguments. The effective method can be one of the methods for the
generic function, or a combination of several of them.
{\bit Generic function\/}:
A function whose behavior depends on the classes or identities of the
arguments supplied to it. A generic function comprises a set of
methods, a lambda-list, a method-combination type, and possibly some
options. The methods define the class-specific behavior and operations
of the generic function. Thus, generic functions are objects that may
be specialized by defining methods to provide class-specific operations.
When a generic function is invoked, the classes of its required
arguments determine which methods will be invoked. The behavior of the
generic function results from which methods are selected for execution,
the order in which the selected methods are called, and how their values
are combined to produce the value or values of the generic function.
{\bit Instance\/}:
Every Lisp object is an instance of some class. The term instance is
used to describe the instance/class relationship of an object to its
class. {\bf make-instance} is used to create new instances of classes
which were defined by {\bf defclass}.
{\bit Local precedence order\/}:
When a class is defined, the order in which its direct superclasses are
mentioned in the defining form is important. Each class has a local
precedence order, which is a list consisting of the class followed by
its direct superclasses in the order mentioned in the defining form.
{\bit Local slot\/}:
A local slot is local to an individual instance. A local slot is
created by giving {\bf :instance} or {\bf :dynamic} as the value of the
{\bf defclass} {\bf :allocation} slot option, or by providing a slot
specifier that omits the {\bf :allocation} slot option (since {\bf
:instance} is the default).
{\bit Metaclass\/}:
Classes are represented by objects that are themselves
instances of classes. The class of the class of an object is termed
the metaclass of that object. The metaclass determines the form of
inheritance used by the classes that are its instances and the
representation of the instances of those classes. The \CLOS\ provides
a default metaclass that is appropriate for most programs; it is called
{\bf standard-class}. The meta-object protocol will allow for defining
and using new metaclasses.
{\bit Method\/}:
An object that defines the class-specific behavior and operations of the
generic function. Each required formal parameter of each method has an
associated parameter specializer, and the method is expected to be
invoked only on arguments that satisfy its parameter specializers. A
method object contains a method function, a set of parameter
specializers that specify when the given method is applicable, and a set
of qualifiers that are used by the method combination to distinguish
among methods.
{\bit Method combination\/}:
Each generic function contains a method-combination type, which controls
the selection of methods, the order in which they are run, and the
values that are returned by the generic function. The \CLOS\ offers a
default method combination type that is appropriate for most user
programs; it is called standard method combination. The \CLOS\ also
provides a facility for declaring new types of method combination for
programs that require them.
{\bit Parameter specializer\/}:
Each method has an ordered set of parameter specializers, that specify
when the given method is applicable. Only required parameters can be
specialized, and there must be a parameter specializer for each required
parameter. For notational simplicity, if some required parameter in a
specialized lambda-list is simply a variable name, its parameter
specializer defaults to the class named {\bf t}.
Parameter specializers are used in the functional interface ({\bf
make-method} and {\bf get-method}).
A parameter specializer name denotes a parameter specializer as follows:
Let $N$ be a parameter specializer name and $P$ be the corresponding
parameter specializer; if $N$ is a class name, then $P$ is the class with
that name; otherwise $N$ equals $P$.
{\bit Parameter specializer name\/}:
Parameter specializer names are used in macros intended as the
user-level interface ({\bf defmethod} and {\bf defmethod-setf}).
Every parameter specializer name is a Common Lisp type specifier, but
the only Common Lisp type specifiers that are valid as parameter
specializer names are: the name of any class, or a list of the form
{\tt ({\bf quote} {\it object\/})}.
{\bit Primary method\/}:
In standard method combination, an unqualified method has the role of
primary method; a primary method defines the main action of the
effective method. For types of method combination defined using the
short form of {\bf define-method-combination}, primary methods are
defined to include not only the unqualified methods, but certain others
as well.
{\bit Qualified method\/}:
A method that has one or more qualifiers is called a {\bit qualified\/}
method.
{\bit Qualifier\/}:
Each method has an ordered set of qualifiers that are used by the method
combination facility to distinguish among methods.
A qualifier is any object other than a list; in other words,
any non-{\bf nil} atom. By convention, qualifiers are usually keyword
symbols.
Standard method combination allows zero qualifiers or a single
qualifier, which is one of: {\bf :after}, {\bf :before}, or {\bf
:around}.
{\bit Reader generic function\/}:
A generic function that enables you to read the value of a slot. {\bf
defclass} has options for automatically generating methods for readers;
these methods are implemented by using {\bf slot-value} and are added to
the appropriate generic functions. It is possible to modify the
behavior of these generic functions by writing methods for them.
{\bit SETF generic function\/}:
A {\bf setf} generic function is called in an expression
such as: ({\bf setf} ({\it symbol arguments\/}) {\it
new-value\/}). One example of {\it symbol\/} is a slot
reader. The macro {\bf defgeneric-options-setf} is used to define
a {\bf setf} generic function.
{\bf setf} generic functions do not have names. The macros {\bf
defmethod-setf} and {\bf defgeneric-options-setf} use {\bf
get-setf-generic-function} to find the generic function they affect.
{\bit SETF method\/}:
A method for a {\bf setf} generic function. {\bf defmethod-setf} is
used to write a {\bf setf} method.
{\bit Shared slot\/}:
A shared slot is shared by all instances of a given class. A shared
slot is created by giving {\bf :class} as the value of the {\bf defclass}
{\bf :allocation} slot option.
{\bit Slot\/}:
An object has zero or more named slots. An object's set of slots is
determined by the object's class. Each slot can hold one value. There
are two kinds of slots: slots that are local to an individual instance
and slots that are shared by all instances of a given class. The {\bf
:allocation} slot option controls the kind of slot that is defined. If
the value of the {\bf :allocation} slot option is {\bf :instance} or
{\bf :dynamic}, a local slot is created. If the value of the {\bf
:allocation} slot option is {\bf :class}, a shared slot is created.
{\bit Slot description\/}:
Another term for slot specifier.
{\bit Slot specifier\/}:
A slot specifier is part of the syntax of {\bf defclass}. A slot
specifier contains the name of a slot, and zero or more slot-options.
{\bit Specialized lambda list\/}:
Each method has a specialized lambda-list, which determines
when that method can be selected. A specialized lambda-list is like
an ordinary lambda-list except that a specialized parameter may occur
instead of the name of a parameter.
{\bit Specialized parameter\/}:
A specialized parameter is a list,
{\tt ({\it variable-name parameter-specializer-name\/})}.
{\bit Standard method combination\/}:
Standard method combination is the name of the default method
combination type.
{\bit Standard-class\/}:
The class {\bf standard-class} is the default class of
classes defined by {\bf defclass}.
{\bit Standard-generic-function\/}:
The class {\bf standard-generic-function} is the default class of
generic functions defined by {\bf defmethod}, {\bf defmethod-setf},
{\bf defgeneric}, or {\bf defgeneric-setf}.
{\bit Standard-method\/}:
The class {\bf standard-method} is the default class of
methods defined by {\bf defmethod} or {\bf defmethod-setf}.
{\bit Standard-type-class\/}:
The class {\bf standard-type-class} is a metaclass of all the classes
that correspond to the standard Common Lisp types specified in {\it
Common Lisp: The Language\/} by Guy L. Steele Jr. The classes whose
metaclass is {\bf standard-type-class} are called standard-type-classes.
For example {\bf array} is a standard-type-class;
{\bf array} is the name of the class for objects of type {\bf array}.
It is not allowed to make an instance of a standard-type-class with {\bf
make-instance}, or to include a standard-type-class as a superclass of a
class.
{\bit Structure-class\/}:
The class {\bf structure-class} is a subclass of {\bf
standard-type-class}. All classes defined by means of {\bf defstruct}
are instances of {\bf structure-class} or a subclass of {\bf
structure-class}.
{\bit Subclass and superclass\/}:
A class whose definition refers to other classes for the purpose of
inheriting from them is said to be a {\bf subclass} of each of those
classes. The classes that are designated for purposes of inheritance
are said to be {\bf superclasses} of the inheriting class. Note that a
class is not considered a subclass nor a superclass of itself.
The set of subclasses of a class is the transitive closure of its direct
subclasses. The set of superclasses of a class is the transitive
closure of its direct superclasses.
{\bit T\/}:
There is a distinguished class named {\bit T\/}. It has no
superclasses, and is a superclass of every class except itself.
{\bit Unqualified method\/}:
A method that has no qualifiers is called an {\bit unqualified\/}
method.
\endSection%{Glossary}
\endSection
\endChapter
\bye
∂11-Mar-87 2204 kempf%hplabsc@hplabs.HP.COM Re: Staticizing
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 11 Mar 87 22:03:55 PST
Received: from hplabsc by hplabs.HP.COM with TCP ; Wed, 11 Mar 87 16:26:05 pst
Received: by hplabsc ; Wed, 11 Mar 87 16:14:11 pst
Date: Wed, 11 Mar 87 16:14:11 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8703120014.AA11352@hplabsc>
To: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Staticizing
I think this discussion is fruitful, and I'm interested in
seeing Gabriel's proposal. At the risk of seeming to postpone
the issue, however, I wonder if we could try to limit discussion
on Monday to Danny's original proposal of the metaobject protocol
(with perhaps some side discussion on issues where a certain
amount of closure has been achieved, like inheritence of slot
options, possibly initialization protocol for STANDARD-CLASS
instances)?
I agree that the issue can't be relegated to the metaobject
protocol, since the issue of hooks into CL DECLARE and THE
should be resolved as well, but the metaobject protocol
may have a role to play.
jak
∂11-Mar-87 2326 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Gabriel's Comments
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Mar 87 23:25:59 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 91182; Wed 11-Mar-87 20:52:15 EST
Date: Wed, 11 Mar 87 20:52 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Gabriel's Comments
To: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
cc: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8703101731.AA00849@hplabsc>
Message-ID: <870311205207.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Tue, 10 Mar 87 09:31:52 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
....
CLASS REDEFINITION
With regard to class redefinition, lazy update would certainly get
rid of having to keep pointers around in classes, but would introduce
an extra operation during method dispatch, slot access, or whatever
operation was chosen to do the update. Since method dispatch is
100% overhead as far as the applications programmer is concerned,
the question is whether the added flexibility of having the class
update automatically is worth the extra time spent checking during
method dispatch. Similarly with slot access.
Method dispatch isn't slowed down, since you simply make there be no
methods applicable to obsolete instances, other than a default method
that updates the instance and tries again. This works well in New
Flavors and I believe has been used in other object systems as well.
Slot access by calling an accessor generic function isn't slowed down
because that goes through method dispatch.
Slot access by calling the SLOT-VALUE function is slowed down, but
probably infinitesimally compared to the cost of looking up the name
of the slot in a table to get the position of the slot.
Slot access by special implementation-dependent compiler-optimized
technique is defined to prefer speed over the ability to change the
class at any instant; see the mention of semantic difficulties on page
2-9. (There used to be a more explicit discussion here. Where did it
go?)
It's probably safe to say that there are a number of things in this
proposal that seem at first glance to be inefficient, but actually
are amenable to clever implementation techniques. Someone should
publish a paper outlining those techniques so all implementors
concerned with maximizing efficiency can use them.
Note that inserting update into dispatch could also interfere
with staticizing a class.
I suspect that everyone means something slightly different by the
term "staticizing a class." But whatever it means, surely it could
be defined to rule out the ability to use change-class on instances
of that class.
Problems with WITH-SLOTS and with inadvertent trashing of important
classes ala` the example with TEXT-BUFFER remain to be solved.
I assume that was the following, from your 23 February message:
3) What happens to methods written on the old class? Do they
stop working?
Only if they depend on an aspect of the class that is no longer true.
Note that there isn't really "an old class" and "a new class"; there
is only one class. Redefining a class updates the existing object
rather than creating a new object.
What if the methods contain a WITH-SLOTS and
some of the slots accessed within the scope of the WITH-SLOTS
disappear?
The semantics of WITH-SLOTS is defined in terms of calling accessor
generic functions (and hence calling accessor methods) and SLOT-VALUE.
So either you get a no-applicable-method error from the accessor
generic function or SLOT-VALUE signals a no-such-slot error.
Automatic instance updating would limit the amount
of optimization that could be done during a WITH-SLOTS expansion,
since changing the number of slots could invalidate any attempts
to directly access the slot values (like, for example, trying
to get rid of the double indirect referencing mentioned above).
Perhaps my earlier answer to this got lost. Double indirection is
not the only possible implementation technique. Also the possibilities
for optimization are enhanced by the "semantic difficulties" note
mentioned above, which essentially says you can't change the class
while a method is executing (it isn't quite that strong). Also in
a multiple inheritance system, doing the optimization I think you are
thinking of (compiling positions of slots directly into compiled methods)
requires some kind of restriction, possibly "staticizing the class",
and in this case either changing the class would be forbidden or
(as in New Flavors with the :ordered-instance-variables option) changing
the class would be permitted but the system would enforce a restriction
that those slots could not move.
What about accessor functions? Are they undefined? Redefined
to give an error?
See the first paragraph on p. 1-11. It's a pity we don't have a more
tutorial-style document, in which answers to questions like this would
be easier to find. The accessor methods go away, the accessor generic
functions remain defined of course, since other classes might also
have methods for them. I'm not sure if we said anywhere what happens
when you call a generic function and there is no applicable method;
I think it ought to signal an error.
4) Automatic instance updating, in and of itself, could have
potentially serious side effects in every day use.
I don't see how the scenario you gave (redefining a class that the
programming environment depends on, and putting a bug into it) is any
different from redefining a function that the programming environment
depends on, and putting a bug into it. An extra powerful programming
environment might have ways to defend itself against both of these
problems, but I don't think any special language features are called for.
In addition, the question of whether changing a class definition
and having instances still be EQ is consistent with Common Lisp's
EQ semantics needs to be resolved.
True. I've been collecting a list of issues like this, and this is on it.
∂11-Mar-87 2328 Moon@STONY-BROOK.SCRC.Symbolics.COM Comments on 87-002, Chapter 1
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Mar 87 23:27:46 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 91196; Wed 11-Mar-87 21:15:48 EST
Date: Wed, 11 Mar 87 21:15 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Comments on 87-002, Chapter 1
To: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
cc: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8702231935.AA19678@hplabsc>
Message-ID: <870311211535.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 23 Feb 87 11:35:56 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
C) INTERACTION BETWEEN CLOS AND CL `DECLARE' AND `THE'
There is no mention in the document of how the CLOS will interact
with CL DECLARE and THE. The requirement that parameter specifiers
be type specifiers (pg. 1-19, paragraph 6) means that TYPEP
must do the right thing when given an instance object and
a valid class name (and presumably TYPEOF must return the class
name as well?) but does that mean I can say:
(DECLARE (TYPE TEXT-BUFFER X))
and:
(THE TEXT-BUFFER X)
I think that was the intention. We should say it explicitly so there
is no possibility of misinterpretation.
CLtL is vague on what happens if I try to bind X to something
not of TYPE TEXT-BUFFER and I have it so DECLAREd (see pg. 158)
but more explicit for THE (pg. 161). And what happens if
I have two TEXT-BUFFER classes, one whose metaclass is
the default and one with metaclass COMMON-OBJECTS-CLASS?
There can only be one class with a given name.
Seems to me an additional set of declarations are needed,
one, perhaps, restricting the metaclass
Could this be done by making all classes in that metaclass
(all instances of that metaclass) have a particular class as
a superclass? For instance, it has been proposed from time
to time that every standard class should have as a superclass
a class called STANDARD-OBJECT. Thus (THE STANDARD-OBJECT x)
would declare that x is an object with STANDARD-CLASS, or a
subclass of STANDARD-CLASS, as its metaclass.
and one for
specifying that a variable name can be bound to an
object of a particular class *or a subclass*, since
the restriction to a single class is covered by TYPE.
I think you're mistaken here. (THE INTEGER x) does not
imply that x is not a FIXNUM, and similarly (THE C x) does
not imply that (CLASS-OF x) is not a subclass of C. I don't
think Common Lisp has any way to declare that an object is of
a given type, and no more-specific type.
This would allow implementations to optimize method lookup
away at compile time to varying degrees, potentially
completely for a TYPE declaration, and partially
for subclass and metaclass declarations.
So far the standard proposal hasn't examined the issues involved in
early binding of classes and compiling-away of these types of decisions.
I think we should be completely open to a proposal here. I don't
think that a late-bound implementation is going to be so slow as to
demand this type of optimization to get anything done, but of course
the amount of speedup available depends on the machine.
∂12-Mar-87 0002 kempf%hplabsc@hplabs.HP.COM Re: Gabriel's Comments
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 12 Mar 87 00:02:23 PST
Received: from hplabsc by hplabs.HP.COM with TCP ; Wed, 11 Mar 87 15:57:43 pst
Received: by hplabsc ; Wed, 11 Mar 87 15:45:54 pst
Date: Wed, 11 Mar 87 15:45:54 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8703112345.AA10871@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Gabriel's Comments
Some further comments on class changing and staticizing.
> With regard to class redefinition, lazy update would certainly
> get rid of having to keep pointers around in classes, but would
> introduce an extra operation during method dispatch, slot access,
> or whatever operation was chosen to do the update. Since method
> dispatch is 100% overhead as far as the applications programmer is
> concerned, the question is whether the added flexibility of having
> the class update automatically is worth the extra time spent
> checking during method dispatch. Similarly with slot access.
>
> Note that inserting update into dispatch could also interfere
> with staticizing a class. Suppose you have finished developing a
> class and now want to staticize it. If method dispatches must check
> whether instances need to be changed, staticization needs not only
> to affect classes but also methods dispatching on the classes,
> since the check for changes in the class must be removed from the
> dispatch.
>
>The issue you bring up here can be characterized in terms of a tradeoff
>between a good development environment and one fully optimized for
>speed.
I think the revelent word here is "environment." How much of the
change-class functionality should be part of the language definition
and how much a part of the environment?
> I assume that when you talk of "staticizing a class" you really
>mean "staticizing a set of classes and generic functions which apply
>only to those classes". And that the former means that you expect not
>to build any subclasses of the staticized classes (or at least have them
>staticized immediately).
Not necessarily. With multimethods, the developer may have some
methods which discriminate on a staticized class through any number or
order of arguments. Building a staticized class may not mean
that you don't want to subclass; in fact, staticized classes
might be build into class libraries for incorporation into
different applications, with developers specializing them
for particular purposes.
> The purpose of the meta-object protocol in
>part is to allow you to change the implementation of a set of classes by
>defining the implementation structure, and optimizations of slot access
>and method lookup. For classes of such metaclasses, neither
>CHANGE-CLASS nor instance updating (CLASS REDEFINITION) need work.
>These are only guaranteed to work for STANDARD-CLASS.
Perhaps using the metaobject protocol to define a STATIC-CLASS
metaclass is one solution. This would mean STANDARD-CLASS leans
heavily towards a prototypying vehicle, however. How STANDARD-CLASS fits
into the Common Lisp DECLARE mechanism (if at all) still needs
to be resolved.
> In addition, the question of whether changing a class
> definition and having instances still be EQ is consistent with
> Common Lisp's EQ semantics needs to be resolved.
>It is the same semantics as EQ when a list structure has been RPLAC'd.
>EQ implies a continuity of history and coreference.
>
That is one way to look at it. Considering the fact that CLtL makes
practically no guarantees about what is EQ, it may leave a big
hole open to implementors. As an example, consider the case with
vectors which are fasled. I've worked with two CL implementations
which take completely opposite approaches. In one, a vector which
is inserted into two places into code that is compiled will later
be EQ when the code is loaded. In the other, this isn't the case.
Integers don't necessarily have to be EQ in CL (and, in fact,
aren't in one implementation). I don't want to get into a long,
philisophical discussion about EQness, but just want to point
out that unless we are very clear about this and about how
CLOS fits in with Common Lisp, we may end up with a certain
amount of implementation chaos.
Jim Kempf kempf@hplabs.hp.com
∂12-Mar-87 0911 RPG Errata and Glossary
To: common-lisp-object-system@SAIL.STANFORD.EDU
We have formatted and test-printed the errata and glossary chapters.
The glossary was rendered into accurate TEX, but we didn't proofread
it at all. We added a meta-object-protocol-like disclaimer to it and
included an attribution to Moon and Sonya. I'm not sure Linda even read
it - I didn't.
The errata was formatted as a corrections and amendments chapter.
True errata (corrections to erroneous facts) were separated out.
Alterations to the text that did not change the meaning were placed
in the amendments section. Also placed there were the wishlist of
clarifications such as the new ``pages'' about TYPEP, SUBTYPEP, et al.
The draft of the ``Inheritance...'' section was separated out at the end
of the amendments. I believe that the wording requires some minor
improvements to eliminate the last of the confusions (such as what happens
when a slot description has a only a :reader option specified), and so it
was labeled a ``draft.''
We removed most of the extraneous comments about the errata when the
comments didn't add to the content; this was done to to make the
corrections and amendments chapter read less like the Common Lisp mailing
list.
We made some minor wording changes to the corrections and amendments
to bring them more in line with the document. Grammatical and punctuation
errors were corrected.
Linda will place the text for these two chapters on SAIL today for your
approval before reproduction.
-rpg-
∂12-Mar-87 0924 Bobrow.pa@Xerox.COM Re: Inheritance of Slots
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 12 Mar 87 09:23:54 PST
Received: from Cabernet.ms by ArpaGateway.ms ; 11 MAR 87 13:10:50 PST
Date: 11 Mar 87 13:10 PST
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Inheritance of Slots
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 11 Mar 87
09:13 PST
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870311-131050-1245@Xerox>
I think we should leave in the :type descriptor. Since none of
you care about it, let be commune with my compiler and propose a
reasonable thing, which will probably be a variant of what is
currently in the spcification.
I am happy to leave it in if you like it. I thought I had been the only
champion, and I have become decidedly neutral.
Danny, we cannot relegate all matters to the metaobject
protocol, though we could.
I agree.
Staticizing: Kempf rightly points out that this is a concern.
I thought I had a scheme to do it similar to the scheme for
staticizing function calls, but I'm now not entirely sure of it. I
hope to rethink it today, but for the moment, Kempf, suffice it to
say I am sympathetic to your concerns.
What is your belief about how sticizing ought to be communicated -- and
what price should one be willing to pay for changing one's mind.
danny
∂12-Mar-87 1217 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Meeting
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 12 Mar 87 12:17:30 PST
Received: from relay2.cs.net by RELAY.CS.NET id ac12427; 12 Mar 87 14:53 EST
Received: from ti-csl by csnet-relay.csnet id af03031; 12 Mar 87 14:48 EST
Received: from Jenner (jenner.ARPA) by tilde id AA26313; Thu, 12 Mar 87 12:30:54 cst
Message-Id: <2751561175-1124785@Jenner>
Date: Thu, 12 Mar 87 12:32:55 CST
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Meeting
In-Reply-To: Msg of 09 Mar 87 1122 PST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Is 9am ok with everyone?
Sure,
Patrick.
∂12-Mar-87 1325 skeene@STONY-BROOK.SCRC.Symbolics.COM Errata and Glossary
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 12 Mar 87 13:25:29 PST
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 91956; Thu 12-Mar-87 16:25:19 EST
Date: Thu, 12 Mar 87 16:25 EST
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Errata and Glossary
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 12 Mar 87 12:11 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870312162513.9.SKEENE@JUNCO.SCRC.Symbolics.COM>
Date: 12 Mar 87 0911 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
We have formatted and test-printed the errata and glossary chapters.
The glossary was rendered into accurate TEX, but we didn't proofread
it at all.
Thank you. Even if there are typos in it, having a Glossary should be
better than not having one.
[text deleted]
Linda will place the text for these two chapters on SAIL today for your
approval before reproduction.
The new Glossary isn't on SAIL yet, so I wasn't able to check it today.
∂12-Mar-87 1448 LGD errata and glossary files
To: common-lisp-object-system@SAIL.STANFORD.EDU
The errata and glossary tex and dvi files are now on [CLS,LSP].
In order to allow time for photocopying tomorrow, I would like to
get all requests for last-minute changes by noon. NOTE: there
were no changes made to the glossary that Sonya provided.
lgd
∂12-Mar-87 2125 Moon@STONY-BROOK.SCRC.Symbolics.COM Errata and Glossary
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 12 Mar 87 21:24:51 PST
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 92335; Fri 13-Mar-87 00:24:22 EST
Date: Fri, 13 Mar 87 00:24 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Errata and Glossary
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 12 Mar 87 12:11 EST from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870313002424.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 12 Mar 87 0911 PST
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
We have formatted and test-printed the errata and glossary chapters.
Linda will place the text for these two chapters on SAIL today for your
approval before reproduction.
Not having heard further from Dick or Linda, I assume the versions of
glossa.dvi dated 3/12/87 14:33 and errata.dvi dated 3/12/87 13:36
on [cls,lsp] are the right ones. I printed these out and looked
them over.
The big disclaimer on the front of the glossary looks rather silly,
since virtually all of the text was taken verbatim from the main
document. Also I had little to do with writing this except insofar as
I wrote text in the main document that was borrowed, so putting my name
on it is silly. If it's all the same to you, I would prefer to delete
the entire first page. The rest of it looks okay, if a bit long-winded.
On p.6, I don't think the definition of "slot description" agrees
with the meta-object chapter, perhaps that glossary entry should just
be deleted.
In the Corrections and Amendments:
In the correction to 2-34 second paragraph, "parameter" was
inadvertently changed to "argument". It should refer to "names of
required parameters."
In the first bullet on page 7, part of the sentence was lost.
According to the order of what? I don't know how to say it grammatically,
but it's the order of the classes that define the slot specifiers.
Otherwise the changes from my version are improvements, and I didn't
notice any old errors while proofreading (although I may have read
this too many times by now to be an effective proofreader of it).
∂12-Mar-87 2232 RPG Here We Go Again
To: common-lisp-object-system@SAIL.STANFORD.EDU
I know the disclaimer is silly, but I don't like to put something in the
hands of the masses that looks like an official document written by us
that has not been checked by us. Someday someone will forget this was
handed out to help with the discussion and think it's the real thing.
That's why the metaobject protocol chapter had the same disclaimer. I'll
remove the authors' names, but leave the disclaimer.
Moon writes:
``In the correction to 2-34 second paragraph, "parameter" was
inadvertently changed to "argument". It should refer to "names of
required parameters."''
I see now that Steele uses the term ``required parameter,'' which we
thought was inconsistent with usage (though we flubbed the rewording
anyhow).
Moon writes:
``In the first bullet on page 7, part of the sentence was lost.
According to the order of what? I don't know how to say it grammatically,
but it's the order of the classes that define the slot specifiers.''
Hm. I thought the ellided material was sufficiently implied. We'll put it
back. Note, though, I think this section needs more work - we were too
tired yesterday to do it ourselves.
-rpg-
∂15-Mar-87 1054 kempf%hplabsc@hplabs.HP.COM Re: Inheritance of Slots
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 15 Mar 87 10:54:41 PST
Received: from hplabsc by hplabs.HP.COM with TCP ; Sun, 15 Mar 87 10:54:56 pst
Received: by hplabsc ; Sun, 15 Mar 87 10:56:56 pst
Date: Sun, 15 Mar 87 10:56:56 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8703151856.AA01005@hplabsc>
To: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Inheritance of Slots
I'll add my vote to flushing :dynamic.
jak
∂16-Mar-87 0144 kempf%hplabsc@hplabs.HP.COM Re: Moon's Comments
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 16 Mar 87 01:44:04 PST
Received: from hplabsc by hplabs.HP.COM with TCP ; Fri, 13 Mar 87 10:27:16 pst
Received: by hplabsc ; Fri, 13 Mar 87 10:27:19 pst
Date: Fri, 13 Mar 87 10:27:19 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8703131827.AA10539@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Moon's Comments
>
> and one for
> specifying that a variable name can be bound to an
> object of a particular class *or a subclass*, since
> the restriction to a single class is covered by TYPE.
>
>I think you're mistaken here. (THE INTEGER x) does not
>imply that x is not a FIXNUM, and similarly (THE C x) does
>not imply that (CLASS-OF x) is not a subclass of C. I don't
>think Common Lisp has any way to declare that an object is of
>a given type, and no more-specific type.
I was going on the basis of the statement on the bottom of
pg. 161, top of pg. 162 of CLtL:
"In effect, this declares that the user undertakes to guarantee
that the values of the form will always be of the specified type."
in the description of THE semantics. A previous disclaimer, however,
states that it is up to the implementation whether this is checked
or not. In addition, on pg. 158, the description of the TYPE DECLARE
specifier:
"In particular, values assigned to variables by SETQ, as well as
the initial values of the variables, must be of the specified type."
implies that subtyping is not allowed. My recollection of the typing
chapter is that subtyping is allowed, however, so the situation is
ambiguous.
jak
∂16-Mar-87 1132 kempf%hplabsc@hplabs.HP.COM Re: is of type...
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 16 Mar 87 11:32:07 PST
Received: from hplabsc by hplabs.HP.COM with TCP ; Mon, 16 Mar 87 11:31:48 pst
Received: by hplabsc ; Mon, 16 Mar 87 11:33:32 pst
Date: Mon, 16 Mar 87 11:33:32 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8703161933.AA12626@hplabsc>
To: Masinter.pa@Xerox.COM
Subject: Re: is of type...
Cc: common-lisp-object-system@sail.stanford.edu
Masinter writes:
>Its pretty clear that "A is of type B" is defined to mean that A
>can be an instance of some sub-type of B. You assert this is false...
After consulting my dog-eared copy of CLtL, it seems as if
this is the sense in which "is of type" is used in CLtL, and
thus there is no ambiguity between Chapters 2 and 4 and Section
9.2 on DECLARE and 9.3 on THE.
I think the fundamental problem here is that it is not possible
to have instances of types in Common Lisp which are more general
(correct me if I'm wrong), with perhaps the exception of DEFSTRUCTS.
For example, it is not possible to have an instance of INTEGER
which is not either a FIXNUM or a BIGNUM.
With DEFSTRUCTS, it is possible to have an instance of
a type A which is a supertype of type B, so DECLAREing a
variable to be of type A does not preclude B , and thus there
is limited potential for compilation optimization. In stock
Common Lisp, however, this probably isn't a problem, since
passing a STRUCT to a function by reference is probably about
the best you can do.
In CLOS, however, it is a problem, since the application developer
might want to optimize out messaging via a declaration, if
the compiler writer and the language specification have provided
that option.
jak